From 6bf073980b8479bae7c94ecd925c4cecef6e5414 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 12 Jul 2003 22:26:07 +0000 Subject: [PATCH] bitkeeper revision 1.339.1.1 (3f108aff8cNSEyxZFIWHZ-zZtSTT2w) Many files: new file Clean up dom0 proc interfaces. Implemented ioremap and /dev/mem. .del-dom0_block.c~63815c1974691c1c: Delete: xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c .del-sched_ops.c~20807e5c2ed6b51: Delete: xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c .del-xi_list~49abab167156959: Delete: tools/internal/xi_list .del-xl_physdisk_proc.c~49451bc26a40fcb2: Delete: xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c .del-mmu.h~6bc56547519b6f96: Delete: xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h .del-dom0.h~6fb656bb4a0c52e1: Delete: xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h .del-dom0_ops.h~fb19960d77217740: Delete: tools/internal/dom0_ops.h .del-dom0_ops.h~5c52b016e619bd2d: Delete: xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h .del-dom0_memory.c~c72c6e5f7fd65d38: Delete: xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c .del-direct_map.c~d2fedc686b334f2a: Delete: xenolinux-2.4.21-sparse/arch/xeno/mm/direct_map.c direct_map.c: Rename: xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c -> xenolinux-2.4.21-sparse/arch/xeno/mm/direct_map.c --- .rootkeys | 18 +- .../xenoserver/control/CommandVbdCreate.java | 4 +- .../control/CommandVbdCreatePhysical.java | 4 +- .../xenoserver/control/CommandVbdList.java | 2 +- tools/internal/Makefile | 70 +- tools/internal/dom0_defs.h | 126 ++- tools/internal/dom0_ops.h | 5 - tools/internal/mem_defs.h | 28 +- tools/internal/xi_build.c | 552 ++++++------ tools/internal/xi_create.c | 96 +-- tools/internal/xi_destroy.c | 88 +- tools/internal/xi_list | 46 - tools/internal/xi_list.c | 76 ++ tools/internal/xi_phys_grant.c | 67 +- tools/internal/xi_phys_probe.c | 64 +- tools/internal/xi_phys_revoke.c | 49 +- tools/internal/xi_sched_domain.c | 32 + tools/internal/xi_sched_global.c | 27 + tools/internal/xi_start.c | 70 +- tools/internal/xi_stop.c | 73 +- tools/internal/xi_usage.c | 64 ++ tools/internal/xi_vifinit | 4 +- xen/common/dom0_ops.c | 38 +- xen/common/domain.c | 3 +- xen/common/kernel.c | 4 +- xen/common/network.c | 8 +- xen/include/hypervisor-ifs/dom0_ops.h | 22 +- xen/include/hypervisor-ifs/network.h | 3 - xen/include/xeno/sched.h | 2 +- xenolinux-2.4.21-sparse/arch/xeno/Makefile | 8 +- xenolinux-2.4.21-sparse/arch/xeno/config.in | 5 + xenolinux-2.4.21-sparse/arch/xeno/defconfig | 5 + .../arch/xeno/drivers/block/Makefile | 2 +- .../arch/xeno/drivers/block/xl_block.c | 27 +- .../arch/xeno/drivers/block/xl_block.h | 3 + .../xeno/drivers/block/xl_physdisk_proc.c | 119 --- .../arch/xeno/drivers/block/xl_segment_proc.c | 13 +- .../arch/xeno/drivers/dom0/Makefile | 2 +- .../arch/xeno/drivers/dom0/dom0_block.c | 27 - .../arch/xeno/drivers/dom0/dom0_core.c | 420 ++------- .../arch/xeno/drivers/dom0/dom0_memory.c | 151 ---- .../arch/xeno/drivers/dom0/dom0_ops.h | 56 -- .../arch/xeno/drivers/dom0/sched_ops.c | 137 --- .../arch/xeno/drivers/dom0/vfr.c | 4 +- .../arch/xeno/kernel/process.c | 3 - xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile | 2 +- .../arch/xeno/mm/get_unmapped_area.c | 114 --- .../arch/xeno/mm/ioremap.c | 143 +--- xenolinux-2.4.21-sparse/drivers/char/mem.c | 807 ++++++++++++++++++ .../include/asm-xeno/dom0.h | 36 - .../include/asm-xeno/hypervisor.h | 2 +- .../include/asm-xeno/mmu.h | 23 - .../include/asm-xeno/mmu_context.h | 11 +- .../include/asm-xeno/multicall.h | 39 + .../include/asm-xeno/pgalloc.h | 6 + .../include/asm-xeno/pgtable.h | 6 +- .../include/asm-xeno/proc_cmd.h | 28 + .../include/asm-xeno/segment.h | 3 + xenolinux-2.4.21-sparse/mkbuildtree | 1 + xenolinux-2.4.21-sparse/mm/memory.c | 16 + xenolinux-2.4.21-sparse/mm/mprotect.c | 344 ++++++++ xenolinux-2.4.21-sparse/mm/mremap.c | 7 + xenolinux-2.4.21-sparse/mm/vmalloc.c | 334 ++++++++ 63 files changed, 2560 insertions(+), 1989 deletions(-) delete mode 100644 tools/internal/dom0_ops.h delete mode 100755 tools/internal/xi_list create mode 100644 tools/internal/xi_list.c create mode 100644 tools/internal/xi_sched_domain.c create mode 100644 tools/internal/xi_sched_global.c create mode 100644 tools/internal/xi_usage.c delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c delete mode 100644 xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c create mode 100644 xenolinux-2.4.21-sparse/drivers/char/mem.c delete mode 100644 xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h delete mode 100644 xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h create mode 100644 xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h create mode 100644 xenolinux-2.4.21-sparse/mm/mprotect.c create mode 100644 xenolinux-2.4.21-sparse/mm/vmalloc.c diff --git a/.rootkeys b/.rootkeys index 037fbbc3f8..9d6ec81b45 100644 --- a/.rootkeys +++ b/.rootkeys @@ -122,19 +122,21 @@ 3eb781fcabCKRogwxJA3-jJKstw9Vg tools/control/xenctl.xml 3eb781fdl4lXWYZzmqDDUAYhAThRqQ tools/internal/Makefile 3eb781fdc539MQQm47rYRCCR3N5i-Q tools/internal/dom0_defs.h -3ee609b3Yr4aggmLSKmhiIzT8-nURA tools/internal/dom0_ops.h 3eb781fdKiQbgozBsgs_zzJQ9ubehw tools/internal/mem_defs.h 3ec61e1bJCeJJu0SsptmDpA1xKvwvw tools/internal/rpm.spec 3eb781fdgbSkh2O6JQS-65Dz4n0ItQ tools/internal/xi_build.c 3eb781fdW1SAyiaC4mTsXq_9fRHh-A tools/internal/xi_create.c 3eb781fdcJ0fF7rWfzAOArW-x4-gwA tools/internal/xi_destroy.c 3ec43c5dmQxGDvgJJXbV1yLxT30Y1A tools/internal/xi_helper -3eb83c3bZeECmphOKOJxSu4Lo1LpBw tools/internal/xi_list +3f108ad5wQm0ZaQ4GXFoUhH1W1aW9w tools/internal/xi_list.c 3f0458aaXhD8BQAggO81gv30RQ-ifA tools/internal/xi_phys_grant.c 3f0458aaJHmlzkDwf0qxEzAcjX55sg tools/internal/xi_phys_probe.c 3f0458aaVAbFSwptQbQAnDOiZlwQ3w tools/internal/xi_phys_revoke.c +3f108adb2b5OkKL6-faG3lMiOYDf_w tools/internal/xi_sched_domain.c +3f108ade1v8weyh1sKx890VTd240Hw tools/internal/xi_sched_global.c 3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c 3eb781fd0Eo9K1jEFCSAVzO51i_ngg tools/internal/xi_stop.c +3f108ae2to5nHRRXfvUK7oxgjcW_yA tools/internal/xi_usage.c 3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile 3ddb79bcCa2VbsMp7mWKlhgwLQUQGA xen/README @@ -516,18 +518,13 @@ 3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c 3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h 3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_ide.c -3f045897EIYU5l5jxFBpeF1Z0ZOTwA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c 3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_scsi.c 3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment.c 3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-sparse/arch/xeno/drivers/console/Makefile 3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-sparse/arch/xeno/drivers/console/console.c 3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile -3e5a4e65Cc7io-vynYob10SlqXTjAQ xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c 3e5a4e65BXtftInNHUC2PjDfPhdZZA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c -3e5a4e65uXAx05p6B1-HU2tijuw8qA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c -3e5a4e65EOOLlPwXnhSuX-iVdWLmnA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h -3e6dba59C8o0kBks7UZ4IW_FY853Aw xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c 3e5a4e65gfn_ltB8ujHMVFApnTTNRQ xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c 3e5a4e65gZBRBB6RsSVg1c9iahigAw xenolinux-2.4.21-sparse/arch/xeno/drivers/network/Makefile 3e5a4e65ZxKrbFetVB84JhrTyZ1YuQ xenolinux-2.4.21-sparse/arch/xeno/drivers/network/network.c @@ -548,13 +545,13 @@ 3e5a4e6637ZDk0BvFEC-aFQs599-ng xenolinux-2.4.21-sparse/arch/xeno/lib/delay.c 3e5a4e66croVgpcJyJuF2ycQw0HuJw xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile 3e5a4e66l8Q5Tv-6B3lQIRmaVbFPzg xenolinux-2.4.21-sparse/arch/xeno/mm/fault.c -3e5a4e66TyNNUEXkr5RxqvQhXK1MQA xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c 3e5a4e668SE9rixq4ahho9rNhLUUFQ xenolinux-2.4.21-sparse/arch/xeno/mm/hypervisor.c 3e5a4e661gLzzff25pJooKIIWe7IWg xenolinux-2.4.21-sparse/arch/xeno/mm/init.c 3f0bed43UUdQichXAiVNrjV-y2Kzcg xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c 3e5a4e66qRlSTcjafidMB6ulECADvg xenolinux-2.4.21-sparse/arch/xeno/vmlinux.lds 3ea53c6em6uzVHSiGqrbbAVofyRY_g xenolinux-2.4.21-sparse/drivers/block/genhd.c 3e5a4e66mrtlmV75L1tjKDg8RaM5gA xenolinux-2.4.21-sparse/drivers/block/ll_rw_blk.c +3f108aeaLcGDgQdFAANLTUEid0a05w xenolinux-2.4.21-sparse/drivers/char/mem.c 3e5a4e66rw65CxyolW9PKz4GG42RcA xenolinux-2.4.21-sparse/drivers/char/tty_io.c 3e5a4e669uzIE54VwucPYtGwXLAbzA xenolinux-2.4.21-sparse/fs/exec.c 3f05a939l8s0eQb_fpMvYiI06cTGlA xenolinux-2.4.21-sparse/fs/partitions/Config.in @@ -564,20 +561,19 @@ 3f05a939_I9vPADPgyVBwUDUxtoeOQ xenolinux-2.4.21-sparse/fs/partitions/xeno.h 3e5a4e66wbeCpsJgVf_U8Jde-CNcsA xenolinux-2.4.21-sparse/include/asm-xeno/bugs.h 3e5a4e66HdSkvIV6SJ1evG_xmTmXHA xenolinux-2.4.21-sparse/include/asm-xeno/desc.h -3f0c3721E5WAnbeoPp7PE35J_Ndxaw xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h 3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw xenolinux-2.4.21-sparse/include/asm-xeno/fixmap.h 3e5a4e67w_DWgjIJ17Tlossu1LGujQ xenolinux-2.4.21-sparse/include/asm-xeno/highmem.h 3e5a4e67YtcyDLQsShhCfQwPSELfvA xenolinux-2.4.21-sparse/include/asm-xeno/hw_irq.h 3e5a4e677VBavzM1UZIEcH1B-RlXMA xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h 3e5a4e673p7PEOyHFm3nHkYX6HQYBg xenolinux-2.4.21-sparse/include/asm-xeno/irq.h 3ead095db_LRUXnxaqs0dA1DWhPoQQ xenolinux-2.4.21-sparse/include/asm-xeno/keyboard.h -3e5a4e67zoNch27qYhEBpr2k6SABOg xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h 3e5a4e678ddsQOpbSiRdy1GRcDc9WA xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h 3e7270deQqtGPSnFxcW4AvJZuTUWfg xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h 3e5a4e67mnQfh-R8KcQCaVo2Oho6yg xenolinux-2.4.21-sparse/include/asm-xeno/page.h 3e5a4e67uTYU5oEnIDjxuaez8njjqg xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h 3e5a4e67X7JyupgdYkgDX19Huj2sAw xenolinux-2.4.21-sparse/include/asm-xeno/pgtable-2level.h 3e5a4e67gr4NLGtQ5CvSLimMYZlkOA xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h +3f108af1qNv8DVSGPv4zpqIU1txCkg xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h 3e5a4e676uK4xErTBDH6XJREn9LSyg xenolinux-2.4.21-sparse/include/asm-xeno/processor.h 3e5a4e67AJPjW-zL7p-xWuA6IVeH1g xenolinux-2.4.21-sparse/include/asm-xeno/ptrace.h 3e5a4e68uJz-xI0IBVMD7xRLQKJDFg xenolinux-2.4.21-sparse/include/asm-xeno/segment.h @@ -591,5 +587,7 @@ 3eba8f878XjouY21EkQBXwYBsPsipQ xenolinux-2.4.21-sparse/lndir-rel 3e6e7c1efbQe93xCvOpOVCnXTMmQ5w xenolinux-2.4.21-sparse/mkbuildtree 3e5a4e68GxCIaFH4sy01v1wjapetaA xenolinux-2.4.21-sparse/mm/memory.c +3f108af5VxPkLv13tXpXgoRKALQtXQ xenolinux-2.4.21-sparse/mm/mprotect.c 3e5a4e681xMPdF9xCMwpyfuYMySU5g xenolinux-2.4.21-sparse/mm/mremap.c 3e5a4e683HKVU-sxtagrDasRB8eBVw xenolinux-2.4.21-sparse/mm/swapfile.c +3f108af81Thhb242EmKjGCYkjx-GJA xenolinux-2.4.21-sparse/mm/vmalloc.c diff --git a/tools/control/src/org/xenoserver/control/CommandVbdCreate.java b/tools/control/src/org/xenoserver/control/CommandVbdCreate.java index 3c1c21aa6c..a1c7c82f15 100644 --- a/tools/control/src/org/xenoserver/control/CommandVbdCreate.java +++ b/tools/control/src/org/xenoserver/control/CommandVbdCreate.java @@ -53,12 +53,12 @@ public class CommandVbdCreate extends Command { String command = vd.dumpForXen(vbd); try { - FileWriter fw = new FileWriter("/proc/xeno/dom0/vhd"); + FileWriter fw = new FileWriter("/proc/xeno/vhd"); fw.write(command); fw.flush(); fw.close(); } catch (IOException e) { - throw new CommandFailedException("Could not write VBD details to /proc/xeno/dom0/vhd", e); + throw new CommandFailedException("Could not write VBD details to /proc/xeno/vhd", e); } return "Created virtual block device " diff --git a/tools/control/src/org/xenoserver/control/CommandVbdCreatePhysical.java b/tools/control/src/org/xenoserver/control/CommandVbdCreatePhysical.java index 2046525529..15b39eab05 100644 --- a/tools/control/src/org/xenoserver/control/CommandVbdCreatePhysical.java +++ b/tools/control/src/org/xenoserver/control/CommandVbdCreatePhysical.java @@ -53,13 +53,13 @@ public class CommandVbdCreatePhysical extends Command { String command = vd.dumpForXen(vbd); try { - FileWriter fw = new FileWriter("/proc/xeno/dom0/vhd"); + FileWriter fw = new FileWriter("/proc/xeno/vhd"); fw.write(command); fw.flush(); fw.close(); } catch (IOException e) { throw new CommandFailedException( - "Could not write VBD details to /proc/xeno/dom0/vhd", + "Could not write VBD details to /proc/xeno/vhd", e); } diff --git a/tools/control/src/org/xenoserver/control/CommandVbdList.java b/tools/control/src/org/xenoserver/control/CommandVbdList.java index e525ee485f..16fd1953c6 100644 --- a/tools/control/src/org/xenoserver/control/CommandVbdList.java +++ b/tools/control/src/org/xenoserver/control/CommandVbdList.java @@ -16,7 +16,7 @@ public class CommandVbdList extends Command { String line; try { - in = new BufferedReader(new FileReader("/proc/xeno/dom0/vhd")); + in = new BufferedReader(new FileReader("/proc/xeno/vhd")); line = in.readLine(); while (line != null) { int domain = -1; diff --git a/tools/internal/Makefile b/tools/internal/Makefile index c39dcf621b..e1b026b199 100644 --- a/tools/internal/Makefile +++ b/tools/internal/Makefile @@ -1,55 +1,27 @@ -CC = gcc -CFLAGS = -Wall -I../../xen/include -I../../xenolinux-2.4.21-sparse/include -XI_CREATE = xi_create -XI_START = xi_start -XI_STOP = xi_stop -XI_DESTROY = xi_destroy -XI_BUILD = xi_build -XI_PHYS_GRANT = xi_phys_grant -XI_PHYS_REVOKE = xi_phys_revoke -XI_PHYS_PROBE = xi_phys_probe - -all: $(XI_CREATE).o $(XI_START).o $(XI_STOP).o $(XI_DESTROY).o $(XI_BUILD).o \ - $(XI_PHYS_GRANT).o $(XI_PHYS_REVOKE).o $(XI_PHYS_PROBE).o - $(CC) -o $(XI_CREATE) $(XI_CREATE).o - $(CC) -o $(XI_BUILD) $(XI_BUILD).o - $(CC) -o $(XI_START) $(XI_START).o - $(CC) -o $(XI_STOP) $(XI_STOP).o - $(CC) -o $(XI_DESTROY) $(XI_DESTROY).o - $(CC) -o $(XI_PHYS_GRANT) $(XI_PHYS_GRANT).o - $(CC) -o $(XI_PHYS_REVOKE) $(XI_PHYS_REVOKE).o - $(CC) -o $(XI_PHYS_PROBE) $(XI_PHYS_PROBE).o - -$(XI_CREATE).o: $(XI_CREATE).c dom0_defs.h dom0_ops.h mem_defs.h - $(CC) $(CFLAGS) -c $(XI_CREATE).c - -internal_domain_build.o: internal_domain_build.c dom0_defs.h dom0_ops.h mem_defs.h - $(CC) $(CFLAGS) -c internal_domain_build.c - -$(XI_START).o: $(XI_START).c dom0_defs.h dom0_ops.h mem_defs.h - $(CC) $(CFLAGS) -c $(XI_START).c - -$(XI_STOP).o: $(XI_STOP).c dom0_defs.h dom0_ops.h mem_defs.h - $(CC) $(CFLAGS) -c $(XI_STOP).c - -$(XI_DESTROY).o: $(XI_DESTROY).c dom0_ops.h dom0_defs.h - $(CC) $(CFLAGS) -c $(XI_DESTROY).c - -$(XI_PHYS_GRANT).o: $(XI_PHYS_GRANT).c - $(CC) $(CFLAGS) -c $(XI_PHYS_GRANT).c - -$(XI_PHYS_REVOKE).o: $(XI_PHYS_REVOKE).c - $(CC) $(CFLAGS) -c $(XI_PHYS_REVOKE).c - -$(XI_PHYS_PROBE).o: $(XI_PHYS_PROBE).c - $(CC) $(CFLAGS) -c $(XI_PHYS_PROBE).c + +CC = gcc +CFLAGS = -Wall -O3 +CFLAGS += -I../../xen/include -I../../xenolinux-2.4.21-sparse/include + +HDRS = $(wildcard *.h) +SRCS = $(wildcard *.c) +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +TARGETS = xi_create xi_start xi_stop xi_destroy xi_build +TARGETS += xi_phys_grant xi_phys_revoke xi_phys_probe xi_list +TARGETS += xi_sched_global xi_sched_domain xi_usage +INSTALL = $(TARGETS) xi_vifinit xi_helper + +all: $(TARGETS) install: all - cp -a xi_list xi_vifinit xi_helper $(XI_CREATE) $(XI_BUILD) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_PHYSDEV_GRANT) $(XI_PHYS_REVOKE) $(XI_PHYS_PROBE).o../../../install/bin - chmod 755 ../../../install/bin/xi_list + cp -a $(INSTALL) ../../../install/bin chmod 755 ../../../install/bin/xi_vifinit chmod 755 ../../../install/bin/xi_helper +clean: + $(RM) *.o *.rpm $(TARGETS) + rpm: all rm -rf staging mkdir staging @@ -58,6 +30,6 @@ rpm: all mv staging/i386/*.rpm . rm -rf staging -clean: - $(RM) *.o *.rpm $(XI_CREATE) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_BUILD) $(XI_PHYS_GRANT) $(XI_PHYS_REVOKE) $(XI_PHYS_PROBE) +%: %.c $(HDRS) Makefile + $(CC) $(CFLAGS) -o $@ $< diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h index e79d85d417..9ef8d0645d 100644 --- a/tools/internal/dom0_defs.h +++ b/tools/internal/dom0_defs.h @@ -1,9 +1,121 @@ -#define PROC_XENO_ROOT "xeno" -#define PROC_CMD "dom0_cmd" -#define PROC_DOM_PREFIX "dom" -#define PROC_DOM_MEM "mem" -#define PROC_DOM_DATA "new_dom_data" -#define PROC_DOMAINS "domains" -#define MAX_PATH 256 +#ifndef __DOM0_DEFS_H__ +#define __DOM0_DEFS_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mem_defs.h" +#include +#include +#include + +#define ERROR(_m) \ + fprintf(stderr, "ERROR: %s\n", (_m)) + +#define PERROR(_m) \ + fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno)) + +static inline int do_privcmd(unsigned int cmd, unsigned long data) +{ + int fd; + + if ( (fd = open("/proc/xeno/privcmd", O_RDWR)) < 0 ) + { + PERROR("Could not open proc interface"); + return -1; + } + + if ( ioctl(fd, cmd, data) < 0 ) + { +#ifndef SILENT_ERRORS_FROM_XEN + PERROR("Error when executing privileged control ioctl"); +#endif + close(fd); + return -1; + } + + close(fd); + return 0; +} + +static inline int xldev_to_physdev(int xldev) +{ + return do_privcmd(IOCTL_PRIVCMD_LINDEV_TO_XENDEV, + (unsigned long)xldev); +} + +static inline int physdev_to_xldev(int physdev) +{ + return do_privcmd(IOCTL_PRIVCMD_XENDEV_TO_LINDEV, + (unsigned long)physdev); +} + +static inline int do_xen_blkmsg(privcmd_blkmsg_t *blkmsg) +{ + return do_privcmd(IOCTL_PRIVCMD_BLKMSG, (unsigned long)blkmsg); +} + +static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall) +{ + return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall); +} + +static inline int do_dom0_op(dom0_op_t *op) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_dom0_op; + hypercall.arg[0] = (unsigned long)op; + + if ( mlock(op, sizeof(*op)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + if ( do_xen_hypercall(&hypercall) < 0 ) + goto out2; + + ret = 0; + + out2: (void)munlock(op, sizeof(*op)); + out1: return ret; +} + +static inline int do_network_op(network_op_t *op) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_network_op; + hypercall.arg[0] = (unsigned long)op; + + if ( mlock(op, sizeof(*op)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + if ( do_xen_hypercall(&hypercall) < 0 ) + goto out2; + + ret = 0; + + out2: (void)munlock(op, sizeof(*op)); + out1: return ret; +} + +#endif /* __DOM0_DEFS_H__ */ diff --git a/tools/internal/dom0_ops.h b/tools/internal/dom0_ops.h deleted file mode 100644 index 0764f8302b..0000000000 --- a/tools/internal/dom0_ops.h +++ /dev/null @@ -1,5 +0,0 @@ - -#define NO_DOM0_OP_T -#include "../../xen/include/hypervisor-ifs/dom0_ops.h" -#undef NO_DOM0_OP_T -#include "../../xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h" diff --git a/tools/internal/mem_defs.h b/tools/internal/mem_defs.h index 4ba84ffaee..4361d6766c 100644 --- a/tools/internal/mem_defs.h +++ b/tools/internal/mem_defs.h @@ -1,24 +1,16 @@ -/* - * memory related definitions needed for userspace domain builder dom0 application. these _need_ to - * be kept in sync with the kernel .h files they were copied over from or something horrible will - * happen. remmember: god kills a kitten every time you forget to keep these in sync. - * - * KAF: Boris, these constants are all fixed by x86 hardware. So the kittens are safe for now :-) - * - * Copyright 2002 by B Dragovic - */ -/* copied over from hypervisor: include/asm-i386/page.h */ +#ifndef __MEM_DEFS_H__ +#define __MEM_DEFS_H__ #define _PAGE_PRESENT 0x001 -#define _PAGE_RW 0x002 -#define _PAGE_USER 0x004 -#define _PAGE_PWT 0x008 -#define _PAGE_PCD 0x010 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PWT 0x008 +#define _PAGE_PCD 0x010 #define _PAGE_ACCESSED 0x020 -#define _PAGE_DIRTY 0x040 +#define _PAGE_DIRTY 0x040 #define _PAGE_PAT 0x080 -#define _PAGE_PSE 0x080 +#define _PAGE_PSE 0x080 #define _PAGE_GLOBAL 0x100 @@ -40,6 +32,4 @@ typedef struct { unsigned long l2_lo; } l2_pgentry_t; #define l2_table_offset(_a) \ ((_a) >> L2_PAGETABLE_SHIFT) -/* local definitions */ - -#define nr_2_page(x) ((x) << PAGE_SHIFT) +#endif /* __MEM_DEFS_H__ */ diff --git a/tools/internal/xi_build.c b/tools/internal/xi_build.c index 805ab22a2a..991666436f 100644 --- a/tools/internal/xi_build.c +++ b/tools/internal/xi_build.c @@ -1,131 +1,95 @@ -/* - * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk - * This code is released under terms and conditions of GNU GPL :). - * Usage: - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "asm-xeno/dom0.h" -#include "hypervisor-ifs/hypervisor-if.h" -#include "dom0_ops.h" + +#include "hypervisor-ifs/dom0_ops.h" #include "dom0_defs.h" #include "mem_defs.h" -#define PERR_STRING "Xeno Domain Builder" - #define GUEST_SIG "XenoGues" #define SIG_LEN 8 -/* Watch for precedence when using thses ones... */ -#define PROC_XENO_DOM0_CMD "/proc/" PROC_XENO_ROOT "/" PROC_CMD -#define PROC_XENO_DOMAINS "/proc" PROC_XENO_ROOT "/" PROC_DOMAINS - -/* - * NB. No ring-3 access in initial guestOS pagetables. Note that we allow - * ring-3 privileges in the page directories, so that the guestOS may later - * decide to share a 4MB region with applications. - */ #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -/* standardized error reporting function */ -static void dberr(char *msg) +static long get_tot_pages(int domain_id) { - printf("%s: %s\n", PERR_STRING, msg); + dom0_op_t op; + op.cmd = DOM0_GETDOMAININFO; + op.u.getdominfo.domain = domain_id; + return (do_dom0_op(&op) < 0) ? -1 : op.u.getdominfo.tot_pages; } -/* status reporting function */ -static void dbstatus(char * msg) +static int get_pfn_list( + int domain_id, unsigned long *pfn_buf, unsigned long max_pfns) { - printf("Domain Builder: %s\n", msg); -} - + dom0_op_t op; + int ret; + op.cmd = DOM0_GETMEMLIST; + op.u.getmemlist.domain = domain_id; + op.u.getmemlist.max_pfns = max_pfns; + op.u.getmemlist.buffer = pfn_buf; + + if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) + { + PERROR("Could not lock pfn list buffer"); + return -1; + } -/* clean up domain's memory allocations */ -static void dom_mem_cleanup(dom_mem_t * dom_mem) -{ - int fd; - struct dom0_unmapdommem_args argbuf; - - fd = open("/proc/xeno/dom0_cmd", O_WRONLY); - if(fd < 0){ - perror("openning /proc/xeno/dom0_cmd"); - return; - } - - argbuf.vaddr = dom_mem->vaddr; - argbuf.start_pfn = dom_mem->start_pfn; - argbuf.tot_pages = dom_mem->tot_pages; + ret = do_dom0_op(&op); - if (ioctl(fd, IOCTL_DOM0_UNMAPDOMMEM, &argbuf) < 0) { - dbstatus("Error unmapping domain's memory.\n"); - } + (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long)); - close(fd); + return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int map_dom_mem(unsigned long pfn, int pages, int dom, - dom_mem_t * dom_mem) +static int send_pgupdates(page_update_request_t *updates, int nr_updates) { - struct dom0_mapdommem_args argbuf; - int fd; - - argbuf.domain = dom; - argbuf.start_pfn = pfn; - argbuf.tot_pages = pages; - - fd = open("/proc/xeno/dom0_cmd", O_RDWR); - if (fd < 0) { - perror("openning /proc/xeno/dom0_cmd"); - return -1; - } - - dom_mem->domain = dom; - dom_mem->start_pfn = pfn; - dom_mem->tot_pages = pages; - dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf); - - if (dom_mem->vaddr == -1) { - perror("mapping domain memory"); - close(fd); - return -1; + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_pt_update; + hypercall.arg[0] = (unsigned long)updates; + hypercall.arg[1] = (unsigned long)nr_updates; + + if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 ) + { + PERROR("Could not lock pagetable update array"); + goto out1; } - close(fd); - return 0; + if ( do_xen_hypercall(&hypercall) < 0 ) + goto out2; + + ret = 0; + + out2: (void)munlock(updates, nr_updates * sizeof(*updates)); + out1: return ret; } -/* read the kernel header, extracting the image size and load address. */ +/* Read the kernel header, extracting the image size and load address. */ static int read_kernel_header(int fd, long dom_size, unsigned long * load_addr, size_t * ksize) { char signature[8]; - char status[MAX_PATH]; + char status[1024]; struct stat stat; - if(fstat(fd, &stat) < 0){ - perror(PERR_STRING); + if ( fstat(fd, &stat) < 0 ) + { + PERROR("Cannot stat the kernel image"); return -1; } - if(stat.st_size > (dom_size << 10)){ + if ( (stat.st_size * 2) > (dom_size << 10) ) + { sprintf(status, "Kernel image size %ld larger than requested " "domain size %ld\n Terminated.\n", stat.st_size, dom_size); - dberr(status); + ERROR(status); return -1; } read(fd, signature, SIG_LEN); - if(strncmp(signature, GUEST_SIG, SIG_LEN)){ - dberr("Kernel image does not contain required signature. " + if ( strncmp(signature, GUEST_SIG, SIG_LEN) ) + { + ERROR("Kernel image does not contain required signature. " "Terminating.\n"); return -1; } @@ -137,62 +101,165 @@ static int read_kernel_header(int fd, long dom_size, return 0; } -/* this is the main guestos setup function, - * returnes domain descriptor structure to be used when launching - * the domain by hypervisor to do some last minute initialization. - * page table initialization is done by making a list of page table - * requests that are handeled by the hypervisor in the ordinary - * manner. this way, many potentially messy things are avoided... - */ -#define PAGE_TO_VADDR(_pfn) ((void *)(dom_mem->vaddr + ((_pfn) * PAGE_SIZE))) -static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd, - unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem) +static int devmem_fd; + +static int init_pfn_mapper(void) +{ + if ( (devmem_fd = open("/dev/mem", O_RDWR)) < 0 ) + { + PERROR("Could not open /dev/mem"); + return -1; + } + return 0; +} + +static void *map_pfn(unsigned long pfn) +{ + void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT); + if ( vaddr == MAP_FAILED ) + { + PERROR("Could not mmap a domain pfn using /dev/mem"); + return NULL; + } + return vaddr; +} + +static void unmap_pfn(void *vaddr) +{ + (void)munmap(vaddr, PAGE_SIZE); +} + +static int clear_domain_page(unsigned long pfn) +{ + void *vaddr = map_pfn(pfn); + if ( vaddr == NULL ) + return -1; + memset(vaddr, 0, PAGE_SIZE); + unmap_pfn(vaddr); + return 0; +} + +static int copy_to_domain_page(unsigned long dst_pfn, void *src_page) +{ + void *vaddr = map_pfn(dst_pfn); + if ( vaddr == NULL ) + return -1; + memcpy(vaddr, src_page, PAGE_SIZE); + unmap_pfn(vaddr); + return 0; +} + +static int setup_guestos( + int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages, + unsigned long virt_load_addr, size_t ksize, dom_meminfo_t *meminfo) { - dom_meminfo_t *meminfo = NULL; unsigned long *page_array = NULL; - page_update_request_t *pgt_updates = NULL; + page_update_request_t *pgt_update_arr = NULL, *pgt_updates = NULL; int alloc_index, num_pt_pages; unsigned long l2tab; unsigned long l1tab = 0; unsigned long num_pgt_updates = 0; - unsigned long count, pt_start; - struct dom0_dopgupdates_args pgupdate_req; - int cmd_fd; - int result; - - meminfo = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t)); - page_array = malloc(dom_mem->tot_pages * 4); - if (!meminfo || !page_array) { - dberr ("Could not allocate memory"); + unsigned long count, pt_start, i, j; + + memset(meminfo, 0, sizeof(*meminfo)); + + if ( init_pfn_mapper() < 0 ) + goto error_out; + + pgt_updates = malloc((tot_pages + 1024) * 3 + * sizeof(page_update_request_t)); + page_array = malloc(tot_pages * sizeof(unsigned long)); + pgt_update_arr = pgt_updates; + if ( (pgt_update_arr == NULL) || (page_array == NULL) ) + { + PERROR("Could not allocate memory"); goto error_out; } - pgt_updates = (page_update_request_t *)dom_mem->vaddr; - alloc_index = dom_mem->tot_pages - 1; - memset(meminfo, 0, sizeof(*meminfo)); + if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages ) + { + PERROR("Could not get the page frame list"); + goto error_out; + } + + /* Load the guest OS image. */ + for ( i = 0; i < ksize; i += PAGE_SIZE ) + { + char page[PAGE_SIZE]; + int size = ((ksize-i) < PAGE_SIZE) ? (ksize-i) : PAGE_SIZE; + if ( read(kernel_fd, page, size) != size ) + { + PERROR("Error reading kernel image, could not" + " read the whole image."); + goto error_out; + } + copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); + } + + /* Load the initial ramdisk image. */ + if ( initrd_fd >= 0 ) + { + struct stat stat; + unsigned long isize; + + if ( fstat(initrd_fd, &stat) < 0 ) + { + PERROR("Could not stat the initrd image"); + goto error_out; + } + isize = stat.st_size; + if ( ((isize + ksize) * 2) > (tot_pages << PAGE_SHIFT) ) + { + ERROR("Kernel + initrd too big to safely fit in domain memory"); + goto error_out; + } - memcpy(page_array, (void *)dom_mem->vaddr, dom_mem->tot_pages * 4); + meminfo->virt_mod_addr = virt_load_addr + i; + meminfo->virt_mod_len = isize; - /* Count bottom-level PTs, rounding up. Include one PTE for shared info. */ + for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE ) + { + char page[PAGE_SIZE]; + int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE; + if ( read(initrd_fd, page, size) != size ) + { + PERROR("Error reading initrd image, could not" + " read the whole image."); + goto error_out; + } + copy_to_domain_page(page_array[i>>PAGE_SHIFT], page); + } + } + + alloc_index = tot_pages - 1; + + /* + * Count bottom-level PTs, rounding up. Include one PTE for shared info. We + * therefore add 1024 because 1 is for shared_info, 1023 is to round up. + */ num_pt_pages = - (l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1024) / 1024; + (l1_table_offset(virt_load_addr) + tot_pages + 1024) / 1024; /* We must also count the page directory. */ num_pt_pages++; /* Index of first PT page. */ - pt_start = dom_mem->tot_pages - num_pt_pages; + pt_start = tot_pages - num_pt_pages; - /* first allocate page for page dir. allocation goes backwards from the - * end of the allocated physical address space. + /* + * First allocate page for page dir. Allocation goes backwards from the end + * of the allocated physical address space. */ - l2tab = *(page_array + alloc_index) << PAGE_SHIFT; - memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE); + l2tab = page_array[alloc_index] << PAGE_SHIFT; + if ( clear_domain_page(page_array[alloc_index]) < 0 ) + goto error_out; alloc_index--; meminfo->l2_pgt_addr = l2tab; - meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages); + meminfo->virt_shinfo_addr = virt_load_addr + (tot_pages << PAGE_SHIFT); - /* pin down l2tab addr as page dir page - causes hypervisor to provide + /* + * Pin down l2tab addr as page dir page - causes hypervisor to provide * correct protection for the page */ pgt_updates->ptr = l2tab | PGREQ_EXTENDED_COMMAND; @@ -206,15 +273,16 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd, * Xen during final setup. */ l2tab += l2_table_offset(virt_load_addr) * sizeof(l2_pgentry_t); - for ( count = 0; count < (dom_mem->tot_pages + 1); count++ ) + for ( count = 0; count < (tot_pages + 1); count++ ) { if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) ) { - l1tab = *(page_array + alloc_index) << PAGE_SHIFT; - memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE); + l1tab = page_array[alloc_index] << PAGE_SHIFT; + if ( clear_domain_page(page_array[alloc_index]) < 0 ) + goto error_out; alloc_index--; - l1tab += l1_table_offset(virt_load_addr + nr_2_page(count)) + l1tab += l1_table_offset(virt_load_addr + (count << PAGE_SHIFT)) * sizeof(l1_pgentry_t); /* make apropriate entry in the page directory */ @@ -226,12 +294,14 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd, } /* The last PTE we consider is filled in later by Xen. */ - if ( count == dom_mem->tot_pages ) break; + if ( count == tot_pages ) break; + printf("%lu: %08lx\n", count, page_array[count]); + if ( count < pt_start ) { pgt_updates->ptr = l1tab; - pgt_updates->val = (*(page_array + count) << PAGE_SHIFT) | L1_PROT; + pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT; pgt_updates++; num_pgt_updates++; l1tab += sizeof(l1_pgentry_t); @@ -240,195 +310,82 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd, { pgt_updates->ptr = l1tab; pgt_updates->val = - ((*(page_array + count) << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; + ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; pgt_updates++; num_pgt_updates++; l1tab += sizeof(l1_pgentry_t); } pgt_updates->ptr = - (*(page_array + count) << PAGE_SHIFT) | PGREQ_MPT_UPDATE; + (page_array[count] << PAGE_SHIFT) | PGREQ_MPT_UPDATE; pgt_updates->val = count; pgt_updates++; num_pgt_updates++; } - meminfo->virt_startinfo_addr = virt_load_addr + nr_2_page(alloc_index - 1); - meminfo->domain = dom; - - free(page_array); - - /* - * Send the page update requests down to the hypervisor. - * NB. We must do this before loading the guest OS image! - */ - if ( (cmd_fd = open(PROC_XENO_DOM0_CMD, O_WRONLY)) < 0 ) - { - dberr ("Could not open " PROC_XENO_DOM0_CMD); - goto error_out; - } - - pgupdate_req.pgt_update_arr = (unsigned long)dom_mem->vaddr; - pgupdate_req.num_pgt_updates = num_pgt_updates; - result = ioctl(cmd_fd, IOCTL_DOM0_DOPGUPDATES, &pgupdate_req); - close(cmd_fd); - if (result < 0) { - dberr ("Could not build domain page tables."); - goto error_out; - } - - /* Load the guest OS image. */ - if( read(kernel_fd, (char *)dom_mem->vaddr, ksize) != ksize ) - { - dberr("Error reading kernel image, could not" - " read the whole image."); - goto error_out; - } - - if( initrd_fd >= 0) - { - struct stat stat; - unsigned long isize; - - if(fstat(initrd_fd, &stat) < 0){ - perror(PERR_STRING); - goto error_out; - } - isize = stat.st_size; - - if( read(initrd_fd, ((char *)dom_mem->vaddr)+ksize, isize) != isize ) - { - dberr("Error reading initrd image, could not" - " read the whole image. Terminating."); - goto error_out; - } - - meminfo->virt_mod_addr = virt_load_addr + ksize; - meminfo->virt_mod_len = isize; + printf("XHDHFDHGFGHFGXXX\n"); + sleep(4); - } + meminfo->virt_startinfo_addr = + virt_load_addr + ((alloc_index-1)< " - "[] \n"); - return -1; + if ( argc < 4 ) + { + fprintf(stderr, "Usage: dom_builder " + "[] \n"); + return 1; } - /* Look up information about the domain */ domain_id = atol(argv[1]); - if ( get_domain_info (domain_id, &pg_head, &tot_pages) != 0 ) + if ( (tot_pages = get_tot_pages(domain_id)) < 0 ) { - perror ("Could not find domain information"); - return -1; + PERROR("Could not find total pages for domain"); + return 1; } - + kernel_fd = open(argv[2], O_RDONLY); - if (kernel_fd < 0) { - perror ("Could not open kernel image"); - return -1; + if ( kernel_fd < 0 ) + { + PERROR("Could not open kernel image"); + return 1; } rc = read_kernel_header(kernel_fd, tot_pages << (PAGE_SHIFT - 10), &load_addr, &ksize); if ( rc < 0 ) - return -1; + return 1; - - /* map domain's memory */ - if ( map_dom_mem(pg_head, tot_pages, - domain_id, &dom_os_image) ) - return -1; - if( (argc > args_start) && (strncmp("initrd=", argv[args_start], 7) == 0) ) { @@ -438,41 +395,40 @@ int main(int argc, char **argv) args_start++; initrd_fd = open(initrd_name, O_RDONLY); - if(initrd_fd < 0){ - perror(PERR_STRING); - return -1; + if ( initrd_fd < 0 ) + { + PERROR("Could not open the initial ramdisk image"); + return 1; } } - /* the following code does the actual domain building */ - meminfo = setup_guestos(domain_id, kernel_fd, initrd_fd, load_addr, - ksize, &dom_os_image); - if (!meminfo) - return -1; + if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages, + load_addr, ksize, &launch_op.u.meminfo) < 0 ) + return 1; - if (initrd_fd >= 0) + if ( initrd_fd >= 0 ) close(initrd_fd); close(kernel_fd); - /* and unmap the new domain's memory image since we no longer need it */ - dom_mem_cleanup(&dom_os_image); - - meminfo->virt_load_addr = load_addr; - meminfo->num_vifs = atoi(argv[3]); - meminfo->cmd_line[0] = '\0'; + launch_op.u.meminfo.domain = domain_id; + launch_op.u.meminfo.virt_load_addr = load_addr; + launch_op.u.meminfo.num_vifs = atoi(argv[3]); + launch_op.u.meminfo.cmd_line[0] = '\0'; cmd_len = 0; - for(count = args_start; count < argc; count++){ - if(cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1){ - dberr("Size of image boot params too big!\n"); + for ( count = args_start; count < argc; count++ ) + { + if ( cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1 ) + { + ERROR("Size of image boot params too big!\n"); break; } - strcat(meminfo->cmd_line, argv[count]); - strcat(meminfo->cmd_line, " "); + strcat(launch_op.u.meminfo.cmd_line, argv[count]); + strcat(launch_op.u.meminfo.cmd_line, " "); cmd_len += strlen(argv[count] + 1); } - /* and launch the domain */ - rc = launch_domain(meminfo); + launch_op.cmd = DOM0_BUILDDOMAIN; + rc = do_dom0_op(&launch_op); - return 0; + return (rc != 0) ? 1 : 0; } diff --git a/tools/internal/xi_create.c b/tools/internal/xi_create.c index ad893285e2..d003979731 100644 --- a/tools/internal/xi_create.c +++ b/tools/internal/xi_create.c @@ -4,90 +4,44 @@ * Usage: */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dom0_ops.h" +#include #include "dom0_defs.h" #include "mem_defs.h" -#include "asm-xeno/dom0.h" - -/***********************************************************************/ static char *argv0 = "internal_domain_create"; -static void ERROR (char *message) -{ - fprintf (stderr, "%s: %s\n", argv0, message); - exit (-1); -} - -static void PERROR (char *message) -{ - fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno)); - exit (-1); -} - -/***********************************************************************/ - static int create_new_domain(long req_mem, char *name) { - char cmd_path[MAX_PATH]; - int cmd_fd; - int dom_id; - struct dom0_createdomain_args argbuf; + int err; + dom0_op_t op; - /* open the /proc command interface */ - sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); - cmd_fd = open(cmd_path, O_RDWR); - if(cmd_fd < 0){ - PERROR ("Could not open PROC_CMD interface"); - return -1; - } + op.cmd = DOM0_CREATEDOMAIN; + op.u.newdomain.memory_kb = req_mem; + strncpy(op.u.newdomain.name, name, MAX_DOMAIN_NAME); + op.u.newdomain.name[MAX_DOMAIN_NAME-1] = '\0'; - argbuf.kb_mem = req_mem; - argbuf.name = name; - dom_id = ioctl(cmd_fd, IOCTL_DOM0_CREATEDOMAIN, &argbuf); - if (dom_id < 0) { - PERROR("creating new domain"); - } - close(cmd_fd); - return dom_id; -} + err = do_dom0_op(&op); -/***********************************************************************/ + return (err < 0) ? err : op.u.newdomain.domain; +} int main(int argc, char **argv) { - int dom_id; - - if (argv[0] != NULL) - { - argv0 = argv[0]; - } - - if(argc != 3) - { - fprintf (stderr, "Usage: %s \n", argv0); - return -1; - } - - dom_id = create_new_domain(atol(argv[1]), argv[2]); - - if(dom_id < 0) + int dom_id; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( argc != 3 ) { - return -1; + fprintf(stderr, "Usage: %s \n", argv0); + return 1; } - - fprintf (stdout, "%d\n", dom_id); - return 0; + + dom_id = create_new_domain(atol(argv[1]), argv[2]); + if ( dom_id < 0 ) + return 1; + + printf("%d\n", dom_id); + return 0; } diff --git a/tools/internal/xi_destroy.c b/tools/internal/xi_destroy.c index bffe1d350d..d6b7a09763 100644 --- a/tools/internal/xi_destroy.c +++ b/tools/internal/xi_destroy.c @@ -1,81 +1,43 @@ -/* - * A very(!) simple program to kill a domain. (c) Boris Dragovic - * Usage: - */ -#include -#include -#include -#include -#include -#include - -#include "dom0_ops.h" +#include "hypervisor-ifs/dom0_ops.h" #include "dom0_defs.h" - -/***********************************************************************/ +#include "mem_defs.h" static char *argv0 = "internal_domain_stop"; -static void ERROR (char *message) -{ - fprintf (stderr, "%s: %s\n", argv0, message); - exit (-1); -} - -static void PERROR (char *message) -{ - fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno)); - exit (-1); -} - -/***********************************************************************/ - -static int do_kill_domain(int dom_id, int force) +static int kill_domain(int dom_id, int force) { - char cmd_path[MAX_PATH]; - dom0_op_t dop; - int cmd_fd; + int err; + dom0_op_t op; - dop.cmd = DOM0_DESTROYDOMAIN; - dop.u.killdomain.domain = dom_id; - dop.u.killdomain.force = force; + op.cmd = DOM0_DESTROYDOMAIN; + op.u.killdomain.domain = dom_id; + op.u.killdomain.force = force; - /* open the /proc command interface */ - sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); - cmd_fd = open(cmd_path, O_WRONLY); - if(cmd_fd < 0){ - PERROR ("Count not open PROC_CMD interface"); - } - - write(cmd_fd, &dop, sizeof(dom0_op_t)); - close(cmd_fd); + err = do_dom0_op(&op); - return 0; + return (err < 0) ? -1 : 0; } int main(int argc, char **argv) { - int ret; - - if (argv[0] != NULL) - { - argv0 = argv[0]; - } - - if ( (argc < 2) || (argc > 3) ) + int ret; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( (argc < 2) || (argc > 3) ) { usage: fprintf(stderr, "Usage: %s [-f] \n", argv0); - fprintf(stderr, " -f: Forces immediate destruction of specified domain\n"); - ret = -1; - goto out; + fprintf(stderr, " -f: Forces immediate destruction of \n"); + return 1; } - - if ( (argc == 3) && strcmp("-f", argv[1]) ) goto usage; - - ret = do_kill_domain(atoi(argv[argc-1]), argc == 3); - -out: - return ret; + + if ( (argc == 3) && strcmp("-f", argv[1]) ) + goto usage; + + ret = kill_domain(atoi(argv[argc-1]), argc == 3); + + return (ret != 0) ? 1 : 0; } diff --git a/tools/internal/xi_list b/tools/internal/xi_list deleted file mode 100755 index e90901818d..0000000000 --- a/tools/internal/xi_list +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# -# xi_list -# -# This is a silly little script to dump the currently running domains. -# The output format is a series of space-separate fields for each domain: -# -# 1. Domain id -# 2. Processor -# 3. Has CPU (1 => true, 0 => false) -# 4. State (integer) -# 5. State (RUNNING, INTERRUPTABLE, UNINTERRUPTABLE, WAIT, SUSPENDED, DYING) -# 6. MCU advance -# 7. Total pages -# 8. Name - -INPUT_FILE=/proc/xeno/domains - -awk -f - $INPUT_FILE < true, 0 => false) + * 4. State (integer) + * 5. State (RUNNING, INTERRUPTIBLE, UNINTERRUPTIBLE, WAIT, SUSPENDED, DYING) + * 6. Pending events (hex value) + * 7. MCU advance + * 8. Total pages + * 9. Name + */ + +/* + * Xen indicates when we've read info on all domains by returning error ESRCH. + * We don't want the helper functiosn to interpret this as a real error! + */ +#define SILENT_ERRORS_FROM_XEN + +#include "hypervisor-ifs/dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +static char *argv0 = "internal_domain_list"; + +static char *statestr(int state) +{ + switch ( state ) + { + case 0: return "RUNNING"; + case 1: return "INTERRUPTIBLE"; + case 2: return "UNINTERRUPTIBLE"; + case 4: return "WAIT"; + case 8: return "SUSPENDED"; + case 16: return "DYING"; + default: return "UNKNOWN"; + } + return NULL; +} + +int main(int argc, char **argv) +{ + dom0_op_t op; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( argc != 1 ) + { + fprintf(stderr, "Usage: %s\n", argv0); + return 1; + } + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdominfo.domain = 0; + while ( do_dom0_op(&op) >= 0 ) + { + printf("%8d %2d %1d %2d %s %08x %8ld %8d %s\n", + op.u.getdominfo.domain, + op.u.getdominfo.processor, + op.u.getdominfo.has_cpu, + op.u.getdominfo.state, + statestr(op.u.getdominfo.state), + op.u.getdominfo.hyp_events, + op.u.getdominfo.mcu_advance, + op.u.getdominfo.tot_pages, + op.u.getdominfo.name); + op.u.getdominfo.domain++; + } + + return 0; +} diff --git a/tools/internal/xi_phys_grant.c b/tools/internal/xi_phys_grant.c index 368414f4f5..05630e2429 100644 --- a/tools/internal/xi_phys_grant.c +++ b/tools/internal/xi_phys_grant.c @@ -1,50 +1,43 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include "hypervisor-ifs/block.h" +#define _GNU_SOURCE +#include "dom0_defs.h" int main(int argc, char *argv[]) { - xp_disk_t buf; - int fd; - char *strbuf; + privcmd_blkmsg_t blkmsg; + xp_disk_t xpd; - if (argc != 7) { - fprintf(stderr, - "Usage: xi_physdev_grant \n"); + if ( argc != 7 ) + { + fprintf(stderr, "Usage: xi_physdev_grant " + " \n"); return 1; } - buf.mode = 0; - if (argv[1][0] == 'r') - buf.mode |= 1; - else if (argv[1][0] == 'w') - buf.mode |= 2; - if (argv[1][1] == 'r') - buf.mode |= 1; - else if (argv[1][1] == 'w') - buf.mode |= 2; - - buf.device = atol(argv[3]); - buf.start_sect = atol(argv[4]); - buf.n_sectors = atol(argv[5]); - buf.partition = atol(argv[6]); - - asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[2]); - fd = open(strbuf, O_WRONLY); - if (fd < 0) { - fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno)); - return 1; + xpd.mode = 0; + if ( strchr(argv[1], 'r') ) + xpd.mode |= PHYSDISK_MODE_R; + if ( strchr(argv[1], 'w') ) + xpd.mode |= PHYSDISK_MODE_W; + + xpd.domain = atol(argv[2]); + xpd.device = xldev_to_physdev(atol(argv[3])); + xpd.start_sect = atol(argv[4]); + xpd.n_sectors = atol(argv[5]); + xpd.partition = atol(argv[6]); + + if ( xpd.device == 0 ) + { + ERROR("Unrecognised device"); + return 1; } - free(strbuf); - write(fd, &buf, sizeof(buf)); - close(fd); + blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT; + blkmsg.buf = &xpd; + blkmsg.buf_size = sizeof(xpd); + + if ( do_xen_blkmsg(&blkmsg) < 0 ) + return 1; return 0; } diff --git a/tools/internal/xi_phys_probe.c b/tools/internal/xi_phys_probe.c index a3dfd8952b..a933e11276 100644 --- a/tools/internal/xi_phys_probe.c +++ b/tools/internal/xi_phys_probe.c @@ -1,50 +1,46 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include "hypervisor-ifs/block.h" +#define _GNU_SOURCE +#include "dom0_defs.h" int main(int argc, char *argv[]) { + privcmd_blkmsg_t blkmsg; physdisk_probebuf_t buf; - int fd; - int x; - char *strbuf; + int i; - if (argc != 2) { + if ( argc != 2 ) + { fprintf(stderr, "Usage: xi_phys_probe \n"); return 1; } - asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]); - fd = open(strbuf, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno)); - return 1; - } - free(strbuf); - memset(&buf, 0, sizeof(buf)); - buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST; + do { - buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST; - read(fd, &buf, sizeof(buf)); - if (!buf.n_aces) - break; - - for (x = 0; x < buf.n_aces; x++) { - char read = (buf.entries[x].mode & 1 ? 'r' : ' '); - char write = (buf.entries[x].mode & 2 ? 'w' : ' '); - printf("%x %x %lx %lx %c%c\n", buf.entries[x].device, - buf.entries[x].partition, - buf.entries[x].start_sect, - buf.entries[x].n_sectors, read, write); + buf.domain = atol(argv[1]); + buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST; + + blkmsg.op = XEN_BLOCK_PHYSDEV_PROBE; + blkmsg.buf = &buf; + blkmsg.buf_size = sizeof(buf); + + if ( do_xen_blkmsg(&blkmsg) < 0 ) + return 1; + + for ( i = 0; i < buf.n_aces; i++ ) + { + char read = (buf.entries[i].mode & 1 ? 'r' : ' '); + char write = (buf.entries[i].mode & 2 ? 'w' : ' '); + printf("%x %x %lx %lx %c%c\n", + physdev_to_xldev(buf.entries[i].device), + buf.entries[i].partition, + buf.entries[i].start_sect, + buf.entries[i].n_sectors, read, write); } + buf.start_ind += buf.n_aces; - } while (buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST); + } + while ( buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST ); + return 0; } diff --git a/tools/internal/xi_phys_revoke.c b/tools/internal/xi_phys_revoke.c index c39146e889..b018b03a24 100644 --- a/tools/internal/xi_phys_revoke.c +++ b/tools/internal/xi_phys_revoke.c @@ -1,40 +1,37 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include "hypervisor-ifs/block.h" +#define _GNU_SOURCE +#include "dom0_defs.h" int main(int argc, char *argv[]) { - xp_disk_t buf; - int fd; - char *strbuf; + privcmd_blkmsg_t blkmsg; + xp_disk_t xpd; - if (argc != 5) { - fprintf(stderr, - "Usage: xi_physdev_revoke \n"); + if ( argc != 5 ) + { + fprintf(stderr, "Usage: xi_physdev_revoke " + " \n"); return 1; } - buf.device = atol(argv[2]); - buf.mode = 0; - buf.start_sect = atol(argv[3]); - buf.n_sectors = atol(argv[4]); + xpd.mode = 0; + xpd.domain = atol(argv[1]); + xpd.device = xldev_to_physdev(atol(argv[2])); + xpd.start_sect = atol(argv[3]); + xpd.n_sectors = atol(argv[4]); - asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]); - fd = open(strbuf, O_WRONLY); - if (fd < 0) { - fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno)); - return 1; + if ( xpd.device == 0 ) + { + ERROR("Unrecognised device"); + return 1; } - free(strbuf); - write(fd, &buf, sizeof(buf)); - close(fd); + blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT; + blkmsg.buf = &xpd; + blkmsg.buf_size = sizeof(xpd); + + if ( do_xen_blkmsg(&blkmsg) < 0 ) + return 1; return 0; } diff --git a/tools/internal/xi_sched_domain.c b/tools/internal/xi_sched_domain.c new file mode 100644 index 0000000000..c8d921f890 --- /dev/null +++ b/tools/internal/xi_sched_domain.c @@ -0,0 +1,32 @@ + +#include "hypervisor-ifs/dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +static char *argv0 = "internal_domain_sched_domain"; + +int main(int argc, char **argv) +{ + dom0_op_t op; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( argc != 6 ) + { + fprintf(stderr, "Usage: %s " + " \n", argv0); + return 1; + } + + op.cmd = DOM0_ADJUSTDOM; + op.u.adjustdom.domain = atoi(argv[1]); + op.u.adjustdom.mcu_adv = atol(argv[1]); + op.u.adjustdom.warp = atol(argv[1]); + op.u.adjustdom.warpl = atol(argv[1]); + op.u.adjustdom.warpu = atol(argv[1]); + if ( do_dom0_op(&op) < 0 ) + return 1; + + return 0; +} diff --git a/tools/internal/xi_sched_global.c b/tools/internal/xi_sched_global.c new file mode 100644 index 0000000000..0c07455b9c --- /dev/null +++ b/tools/internal/xi_sched_global.c @@ -0,0 +1,27 @@ + +#include "hypervisor-ifs/dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +static char *argv0 = "internal_domain_sched_global"; + +int main(int argc, char **argv) +{ + dom0_op_t op; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( argc != 2 ) + { + fprintf(stderr, "Usage: %s \n", argv0); + return 1; + } + + op.cmd = DOM0_BVTCTL; + op.u.bvtctl.ctx_allow = atol(argv[1]); + if ( do_dom0_op(&op) < 0 ) + return 1; + + return 0; +} diff --git a/tools/internal/xi_start.c b/tools/internal/xi_start.c index c6826c4874..b21cc84f9f 100644 --- a/tools/internal/xi_start.c +++ b/tools/internal/xi_start.c @@ -1,77 +1,37 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dom0_ops.h" +#include "hypervisor-ifs/dom0_ops.h" #include "dom0_defs.h" #include "mem_defs.h" -/***********************************************************************/ - static char *argv0 = "internal_domain_start"; -static void ERROR (char *message) -{ - fprintf (stderr, "%s: %s\n", argv0, message); - exit (-1); -} - -static void PERROR (char *message) -{ - fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno)); - exit (-1); -} - -/***********************************************************************/ - static int start_domain(int id) { - char cmd_path[MAX_PATH]; - dom0_op_t dop; - int cmd_fd; - - /* Set up the DOM0_STARTDOMAIN command */ - dop.cmd = DOM0_STARTDOMAIN; - dop.u.meminfo.domain = id; + int err; + dom0_op_t op; - /* open the /proc command interface */ - sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); - cmd_fd = open(cmd_path, O_WRONLY); - if(cmd_fd < 0){ - PERROR ("Count not open PROC_CMD interface"); - } + op.cmd = DOM0_STARTDOMAIN; + op.u.meminfo.domain = id; - /* Issue the command */ - write(cmd_fd, &dop, sizeof(dom0_op_t)); - close(cmd_fd); + err = do_dom0_op(&op); - return 0; + return (err < 0) ? -1 : 0; } -/***********************************************************************/ - int main(int argc, char **argv) { - int rc; + int rc; - if (argv[0] != NULL) - { - argv0 = argv[0]; - } + if ( argv[0] != NULL ) + argv0 = argv[0]; - if(argc != 2) + if ( argc != 2 ) { - fprintf (stderr, "Usage: %s \n", argv0); - return -1; + fprintf(stderr, "Usage: %s \n", argv0); + return 1; } - rc = start_domain(atol(argv[1])); + rc = start_domain(atol(argv[1])); - return rc; + return (rc != 0) ? 1 : 0; } diff --git a/tools/internal/xi_stop.c b/tools/internal/xi_stop.c index 6f2437ca14..5cd732df3a 100644 --- a/tools/internal/xi_stop.c +++ b/tools/internal/xi_stop.c @@ -1,79 +1,36 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dom0_ops.h" +#include "hypervisor-ifs/dom0_ops.h" #include "dom0_defs.h" #include "mem_defs.h" -/***********************************************************************/ - static char *argv0 = "internal_domain_stop"; -static void ERROR (char *message) -{ - fprintf (stderr, "%s: %s\n", argv0, message); - exit (-1); -} - -static void PERROR (char *message) -{ - fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno)); - exit (-1); -} - -/***********************************************************************/ - static int stop_domain(int id) { - dom0_newdomain_t * dom_data; - char cmd_path[MAX_PATH]; - char dom_id_path[MAX_PATH]; - dom0_op_t dop; - int cmd_fd; - int id_fd; + int err; + dom0_op_t op; - /* Set up the DOM0_STOPDOMAIN command */ - dop.cmd = DOM0_STOPDOMAIN; - dop.u.meminfo.domain = id; - - /* open the /proc command interface */ - sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD); - cmd_fd = open(cmd_path, O_WRONLY); - if(cmd_fd < 0){ - PERROR ("Count not open PROC_CMD interface"); - } + op.cmd = DOM0_STOPDOMAIN; + op.u.meminfo.domain = id; - /* Issue the command */ - write(cmd_fd, &dop, sizeof(dom0_op_t)); - close(cmd_fd); + err = do_dom0_op(&op); - return 0; + return (err < 0) ? -1 : 0; } -/***********************************************************************/ - int main(int argc, char **argv) { - int rc; + int rc; - if (argv[0] != NULL) - { - argv0 = argv[0]; - } + if ( argv[0] != NULL ) + argv0 = argv[0]; - if(argc != 2) + if ( argc != 2 ) { - fprintf (stderr, "Usage: %s \n", argv0); - return -1; + fprintf(stderr, "Usage: %s \n", argv0); + return 1; } - rc = stop_domain(atol(argv[1])); + rc = stop_domain(atol(argv[1])); - return rc; + return (rc != 0) ? 1 : 0; } diff --git a/tools/internal/xi_usage.c b/tools/internal/xi_usage.c new file mode 100644 index 0000000000..3cd61431e5 --- /dev/null +++ b/tools/internal/xi_usage.c @@ -0,0 +1,64 @@ + +#include "hypervisor-ifs/dom0_ops.h" +#include "dom0_defs.h" +#include "mem_defs.h" + +static char *argv0 = "internal_domain_usage"; + +int main(int argc, char **argv) +{ + dom0_op_t op; + network_op_t netop; + int i, domain, vifs[32]; + + if ( argv[0] != NULL ) + argv0 = argv[0]; + + if ( argc != 2 ) + { + fprintf(stderr, "Usage: %s \n", argv0); + return 1; + } + + domain = atol(argv[1]); + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdominfo.domain = domain; + if ( do_dom0_op(&op) < 0 ) + return 1; + + printf("cpu%d: %lld\n", + op.u.getdominfo.processor, + op.u.getdominfo.cpu_time); + + if ( mlock(vifs, sizeof(vifs)) != 0 ) + { + PERROR("Could not lock memory for network query buffer"); + return 1; + } + + netop.cmd = NETWORK_OP_VIFQUERY; + netop.u.vif_query.domain = domain; + netop.u.vif_query.buf = vifs; + if ( do_network_op(&netop) < 0 ) + return 1; + + for ( i = 1; i <= vifs[0]; i++ ) + { + netop.cmd = NETWORK_OP_VIFGETINFO; + netop.u.vif_getinfo.domain = domain; + netop.u.vif_getinfo.vif = vifs[i]; + if ( do_network_op(&netop) < 0 ) + return 1; + + printf("vif%d: sent %lld bytes (%lld packets) " + "received %lld bytes (%lld packets)\n", + vifs[i], + netop.u.vif_getinfo.total_bytes_sent, + netop.u.vif_getinfo.total_packets_sent, + netop.u.vif_getinfo.total_bytes_received, + netop.u.vif_getinfo.total_packets_received); + } + + return 0; +} diff --git a/tools/internal/xi_vifinit b/tools/internal/xi_vifinit index feac666bb6..0da845984b 100755 --- a/tools/internal/xi_vifinit +++ b/tools/internal/xi_vifinit @@ -16,10 +16,10 @@ then fi #outbound rule: -echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/vfr +echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/xeno/vfr #inbound rule: -echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/vfr +echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/xeno/vfr #----] done. diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 281fb509b9..9e6269b294 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -146,9 +146,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op) ret = p->domain; op.u.newdomain.domain = ret; - op.u.newdomain.pg_head = - list_entry(p->pg_head.next, struct pfn_info, list) - - frame_table; copy_to_user(u_dom0_op, &op, sizeof(op)); exit_create: @@ -189,16 +186,38 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_GETMEMLIST: { int i; - unsigned long pfn = op.u.getmemlist.start_pfn; + struct task_struct * p = find_domain_by_id(op.u.getmemlist.domain); + unsigned long max_pfns = op.u.getmemlist.max_pfns; + unsigned long pfn; unsigned long *buffer = op.u.getmemlist.buffer; struct list_head *list_ent; - for ( i = 0; i < op.u.getmemlist.num_pfns; i++ ) + ret = -EINVAL; + if ( p != NULL ) { - /* XXX We trust DOM0 to give us a safe buffer. XXX */ - *buffer++ = pfn; - list_ent = frame_table[pfn].list.next; + list_ent = p->pg_head.next; pfn = list_entry(list_ent, struct pfn_info, list) - frame_table; + + for ( i = 0; (i < max_pfns) && (list_ent != &p->pg_head); i++ ) + { + if ( put_user(pfn, buffer) ) + { + ret = -EFAULT; + goto out_getmemlist; + } + buffer++; + list_ent = frame_table[pfn].list.next; + pfn = list_entry(list_ent, struct pfn_info, list) - + frame_table; + } + + op.u.getmemlist.num_pfns = i; + copy_to_user(u_dom0_op, &op, sizeof(op)); + + ret = 0; + + out_getmemlist: + put_task_struct(p); } } break; @@ -227,9 +246,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op.u.getdominfo.state = p->state; op.u.getdominfo.hyp_events = p->hyp_events; op.u.getdominfo.mcu_advance = p->mcu_advance; - op.u.getdominfo.pg_head = - list_entry(p->pg_head.next, struct pfn_info, list) - - frame_table; op.u.getdominfo.tot_pages = p->tot_pages; op.u.getdominfo.cpu_time = p->cpu_time; } diff --git a/xen/common/domain.c b/xen/common/domain.c index 06e67e7dc5..90cf1cd161 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -462,6 +462,7 @@ static unsigned long alloc_page_from_domain(unsigned long * cur_addr, * userspace dom0 and final setup is being done by final_setup_guestos. */ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, + unsigned int num_vifs, char *phy_data_start, unsigned long data_len, char *cmdline, unsigned long initrd_len) { @@ -689,7 +690,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params, } /* Add virtual network interfaces and point to them in startinfo. */ - while (params->num_vifs-- > 0) { + while (num_vifs-- > 0) { net_vif = create_net_vif(dom); shared_rings = net_vif->shared_rings; if (!shared_rings) panic("no network ring!\n"); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index d403717e55..999c88fd4b 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -197,9 +197,7 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) start_of_day(); /* Create initial domain 0. */ - dom0_params.num_vifs = 1; dom0_params.memory_kb = opt_dom0_mem; - new_dom = do_newdomain(0, 0); if ( new_dom == NULL ) panic("Error creating domain 0\n"); @@ -209,7 +207,7 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) * present, is an initrd ramdisk */ if ( setup_guestos(new_dom, - &dom0_params, + &dom0_params, 1, (char *)MAX_DIRECTMAP_ADDRESS, mod[mbi->mods_count-1].mod_end - mod[0].mod_start, __va(mod[0].string), diff --git a/xen/common/network.c b/xen/common/network.c index 30cdf81441..f8526c1854 100644 --- a/xen/common/network.c +++ b/xen/common/network.c @@ -8,7 +8,6 @@ * Copyright (c) 2002-2003, A K Warfield and K A Fraser */ -#include #include #include #include @@ -20,6 +19,7 @@ #include #include #include +#include net_rule_ent_t *net_rule_list; /* global list of rules */ kmem_cache_t *net_vif_cache; @@ -222,7 +222,7 @@ int vif_query(vif_query_t *vq) if ( !(p = find_domain_by_id(vq->domain)) ) { buf[0] = -1; copy_to_user(vq->buf, buf, sizeof(int)); - return -ENOSYS; + return -ESRCH; } for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) @@ -524,12 +524,13 @@ long do_network_op(network_op_t *u_network_op) { long ret=0; network_op_t op; - + if ( current->domain != 0 ) return -EPERM; if ( copy_from_user(&op, u_network_op, sizeof(op)) ) return -EFAULT; + switch ( op.cmd ) { @@ -566,6 +567,7 @@ long do_network_op(network_op_t *u_network_op) { ret = vif_query(&op.u.vif_query); } + break; default: ret = -ENOSYS; diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index b437acec26..e617866090 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -26,11 +26,11 @@ typedef struct dom0_newdomain_st { - unsigned int domain; // return parameter + /* IN parameters. */ unsigned int memory_kb; - unsigned int num_vifs; // temporary - unsigned long pg_head; // return parameter char name[MAX_DOMAIN_NAME]; + /* OUT parameters. */ + unsigned int domain; } dom0_newdomain_t; typedef struct dom0_killdomain_st @@ -41,14 +41,17 @@ typedef struct dom0_killdomain_st typedef struct dom0_getmemlist_st { - unsigned long start_pfn; + /* IN variables. */ + unsigned int domain; + unsigned long max_pfns; + void *buffer; + /* OUT variables. */ unsigned long num_pfns; - void *buffer; } dom0_getmemlist_t; typedef struct domain_launch { - unsigned int domain; + unsigned int domain; unsigned long l2_pgt_addr; unsigned long virt_load_addr; unsigned long virt_shinfo_addr; @@ -75,14 +78,15 @@ typedef struct dom0_adjustdom_st typedef struct dom0_getdominfo_st { - unsigned int domain; /* All returns except domain */ + /* IN variables. */ + unsigned int domain; + /* OUT variables. */ char name[MAX_DOMAIN_NAME]; int processor; int has_cpu; int state; int hyp_events; unsigned long mcu_advance; - unsigned long pg_head; unsigned int tot_pages; long long cpu_time; } dom0_getdominfo_t; @@ -93,7 +97,6 @@ typedef struct dom0_iopl_st unsigned int iopl; } dom0_iopl_t; -#ifndef NO_DOM0_OP_T typedef struct dom0_op_st { unsigned long cmd; @@ -110,6 +113,5 @@ typedef struct dom0_op_st } u; } dom0_op_t; -#endif #endif diff --git a/xen/include/hypervisor-ifs/network.h b/xen/include/hypervisor-ifs/network.h index 09703df925..d2e57cd0fb 100644 --- a/xen/include/hypervisor-ifs/network.h +++ b/xen/include/hypervisor-ifs/network.h @@ -12,9 +12,6 @@ #ifndef __RING_H__ #define __RING_H__ -#include - - typedef struct tx_req_entry_st { unsigned short id; diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 351afa5e8d..ffec7d427b 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -226,7 +226,7 @@ extern struct task_struct first_task_struct; extern struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu); extern int setup_guestos( - struct task_struct *p, dom0_newdomain_t *params, + struct task_struct *p, dom0_newdomain_t *params, unsigned int num_vifs, char *data_start, unsigned long data_len, char *cmdline, unsigned long initrd_len); extern int final_setup_guestos(struct task_struct *p, dom_meminfo_t *); diff --git a/xenolinux-2.4.21-sparse/arch/xeno/Makefile b/xenolinux-2.4.21-sparse/arch/xeno/Makefile index 6565e93645..89777dc9e9 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/Makefile +++ b/xenolinux-2.4.21-sparse/arch/xeno/Makefile @@ -48,14 +48,18 @@ HEAD := arch/xeno/kernel/head.o arch/xeno/kernel/init_task.o SUBDIRS += arch/xeno/kernel arch/xeno/mm arch/xeno/lib SUBDIRS += arch/xeno/drivers/console arch/xeno/drivers/network -SUBDIRS += arch/xeno/drivers/dom0 arch/xeno/drivers/block -SUBDIRS += arch/xeno/drivers/balloon +SUBDIRS += arch/xeno/drivers/block arch/xeno/drivers/balloon +ifdef CONFIG_XENO_PRIV +SUBDIRS += arch/xeno/drivers/dom0 +endif CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o CORE_FILES += arch/xeno/drivers/console/con.o CORE_FILES += arch/xeno/drivers/block/blk.o CORE_FILES += arch/xeno/drivers/network/net.o +ifdef CONFIG_XENO_PRIV CORE_FILES += arch/xeno/drivers/dom0/dom0.o +endif CORE_FILES += arch/xeno/drivers/balloon/balloon_driver.o LIBS := $(TOPDIR)/arch/xeno/lib/lib.a $(LIBS) $(TOPDIR)/arch/xeno/lib/lib.a diff --git a/xenolinux-2.4.21-sparse/arch/xeno/config.in b/xenolinux-2.4.21-sparse/arch/xeno/config.in index 6ae2bca111..a25e336457 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/config.in +++ b/xenolinux-2.4.21-sparse/arch/xeno/config.in @@ -12,6 +12,11 @@ define_bool CONFIG_SBUS n define_bool CONFIG_UID16 y +mainmenu_option next_comment +comment 'Privileged guest OS' +bool 'Support for privileged operations (domain 0)' CONFIG_XENO_PRIV +endmenu + mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL diff --git a/xenolinux-2.4.21-sparse/arch/xeno/defconfig b/xenolinux-2.4.21-sparse/arch/xeno/defconfig index 53314262a9..4bcc51c3fa 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/defconfig +++ b/xenolinux-2.4.21-sparse/arch/xeno/defconfig @@ -7,6 +7,11 @@ CONFIG_ISA=y # CONFIG_SBUS is not set CONFIG_UID16=y +# +# Privileged guest OS +# +CONFIG_XENO_PRIV=y + # # Code maturity level options # diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/Makefile b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/Makefile index c6997d2717..6423104172 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/Makefile +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/Makefile @@ -1,3 +1,3 @@ O_TARGET := blk.o -obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o xl_physdisk_proc.o +obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c index dbaffb76d9..565b07238d 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c @@ -43,6 +43,31 @@ static inline void signal_requests_to_xen(void) HYPERVISOR_block_io_op(); } + +inline kdev_t physdev_to_xldev(unsigned short physdev) +{ + switch (physdev & XENDEV_TYPE_MASK) { + case XENDEV_IDE: + if ( (physdev & XENDEV_IDX_MASK) < XLIDE_DEVS_PER_MAJOR) { + return MKDEV(XLIDE_MAJOR_0, + (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); + } else if ( (physdev & XENDEV_IDX_MASK) < (XLIDE_DEVS_PER_MAJOR * 2)) { + return MKDEV(XLIDE_MAJOR_1, + (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); + } + break; + case XENDEV_SCSI: + return MKDEV(XLSCSI_MAJOR, + (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT); + case XENDEV_VIRTUAL: + return MKDEV(XLVIRT_MAJOR, + (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT); + } + + return 0; +} + + /* Convert from a XenoLinux major device to the Xen-level 'physical' device */ inline unsigned short xldev_to_physdev(kdev_t xldev) { @@ -69,8 +94,6 @@ inline unsigned short xldev_to_physdev(kdev_t xldev) break; } - if ( physdev == 0 ) BUG(); - return physdev; } diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h index ac7e7ae97a..00056bf09e 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h @@ -104,4 +104,7 @@ extern struct gendisk *xlscsi_gendisk; extern int xlsegment_hwsect(int minor); extern struct gendisk *xlsegment_gendisk; +extern unsigned short xldev_to_physdev(kdev_t xldev); +extern kdev_t physdev_to_xldev(unsigned short physdev); + #endif /* __XL_BLOCK_H__ */ diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c deleted file mode 100644 index cda22db128..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c +++ /dev/null @@ -1,119 +0,0 @@ -/* We stuff the domain number into the proc_dir_entry data pointer. */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xl_block.h" - -extern int xenolinux_control_msg(int operration, char *buffer, int size); -extern unsigned short xldev_to_physdev(kdev_t xldev); - -dev_t physdev_to_xldev(unsigned short physdev) -{ - switch (physdev & XENDEV_TYPE_MASK) { - case XENDEV_IDE: - if ( (physdev & XENDEV_IDX_MASK) < XLIDE_DEVS_PER_MAJOR) { - return MKDEV(XLIDE_MAJOR_0, - (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); - } else if ( (physdev & XENDEV_IDX_MASK) < (XLIDE_DEVS_PER_MAJOR * 2)) { - return MKDEV(XLIDE_MAJOR_1, - (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT); - } - break; - case XENDEV_SCSI: - return MKDEV(XLSCSI_MAJOR, - (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT); - case XENDEV_VIRTUAL: - return MKDEV(XLVIRT_MAJOR, - (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT); - } - printk(KERN_ALERT "Unrecognised xl device: %x\n", physdev); - BUG(); - return -1; -} - -static ssize_t proc_read_phd(struct file *file, char *buff, size_t size, - loff_t * off) -{ - physdisk_probebuf_t *buf; - int res; - struct proc_dir_entry *pde; - int x; - - if (size != sizeof(physdisk_probebuf_t)) - return -EINVAL; - - buf = kmalloc(sizeof(physdisk_probebuf_t), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - pde = file->f_dentry->d_inode->u.generic_ip; - buf->domain = (int) pde->data; - - /* The offset reported by lseek and friends doesn't have to be in - bytes, and it's marginally easier to say that it's in records, so - that's what we do. */ - buf->start_ind = *off; - res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_PROBE, (void *) buf, - sizeof(physdisk_probebuf_t)); - *off += buf->n_aces; - - if (res) - res = -EINVAL; - else { - for (x = 0; x < buf->n_aces; x++) - buf->entries[x].device = - physdev_to_xldev(buf->entries[x].device); - res = sizeof(physdisk_probebuf_t); - if (copy_to_user(buff, buf, sizeof(physdisk_probebuf_t))) { - res = -EFAULT; - } - } - kfree(buf); - return res; -} - -static int proc_write_phd(struct file *file, const char *buffer, - size_t count, loff_t * ignore) -{ - char *local; - int res; - xp_disk_t *xpd; - struct proc_dir_entry *pde; - - if (count != sizeof(xp_disk_t)) - return -EINVAL; - - local = kmalloc(count + 1, GFP_KERNEL); - if (!local) - return -ENOMEM; - if (copy_from_user(local, buffer, count)) { - res = -EFAULT; - goto out; - } - - xpd = (xp_disk_t *) local; - - pde = file->f_dentry->d_inode->u.generic_ip; - xpd->domain = (int) pde->data; - xpd->device = xldev_to_physdev(xpd->device); - - res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_GRANT, local, count); - if (res == 0) - res = count; - else - res = -EINVAL; - out: - kfree(local); - return res; -} - -struct file_operations dom0_phd_fops = { - read:proc_read_phd, - write:proc_write_phd -}; diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c index d1b12e203d..464707362a 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c @@ -12,9 +12,6 @@ static struct proc_dir_entry *vhd; -extern unsigned short xldev_to_physdev(kdev_t xldev); -extern dev_t physdev_to_xldev(unsigned short physdev); - static void *proc_vhd_next(struct seq_file *s, void *v, loff_t *pos) { xen_segment_info_t *data; @@ -310,11 +307,13 @@ static struct file_operations proc_vhd_operations = { int __init xlseg_proc_init(void) { - vhd = create_proc_entry("xeno/dom0/vhd", 0600, NULL); - if (vhd == NULL) - { + if ( !(start_info.flags & SIF_PRIVILEGED) ) + return 0; + + vhd = create_proc_entry("xeno/vhd", 0600, NULL); + if ( vhd == NULL ) panic ("xlseg_init: unable to create vhd proc entry\n"); - } + vhd->data = NULL; vhd->proc_fops = &proc_vhd_operations; vhd->owner = THIS_MODULE; diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile index eeb3413842..9030801f14 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile @@ -1,3 +1,3 @@ O_TARGET := dom0.o -obj-y := dom0_memory.o dom0_core.o vfr.o sched_ops.o +obj-y := dom0_core.o vfr.o include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c deleted file mode 100644 index 97d4a65b78..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * domain 0 block driver interface - * - */ - -#include -#include -#include -#include - -static int __init init_module(void) -{ - request_module("xl_block"); - printk("Successfully installed domain 0 block interface\n"); - - - return 0; -} - -static void __exit cleanup_module(void) -{ - printk("Successfully de-installed domain-0 block interface\n"); - return 0; -} - -module_init(init_module); -module_exit(cleanup_module); diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c index c31c2d2410..837dd6dad0 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -3,7 +3,7 @@ * * Interface to privileged domain-0 commands. * - * Copyright (c) 2002, K A Fraser, B Dragovic + * Copyright (c) 2002-2003, K A Fraser, B Dragovic */ #include @@ -14,7 +14,6 @@ #include #include #include - #include #include #include @@ -29,392 +28,117 @@ #include #include #include -#include - -#include "dom0_ops.h" - -#define MAP_DISCONT 1 +#include +#include -/* Private proc-file data structures. */ -typedef struct proc_data { - unsigned int domain; - unsigned long map_size; -} dom_procdata_t; - -/* XXX this certainly shouldn't be here. */ -extern struct file_operations dom0_phd_fops; +#include "../block/xl_block.h" struct proc_dir_entry *xeno_base; -static struct proc_dir_entry *dom0_cmd_intf; -static struct proc_dir_entry *dom_list_intf; +static struct proc_dir_entry *privcmd_intf; -int direct_unmap(struct mm_struct *, unsigned long, unsigned long); -unsigned long direct_mmap(unsigned long phys_addr, unsigned long size, - pgprot_t prot, int flag, int tot_pages); -struct list_head * find_direct(struct list_head *, unsigned long); -static ssize_t dom_usage_read(struct file * file, char * buff, size_t size, loff_t * off) +static int privcmd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data) { - char str[256]; - int vifs[32]; - dom0_op_t op; - network_op_t netop; - int i, end; - unsigned int domain; - static int finished = 0; + int ret = 0; - if ( finished ) + switch ( cmd ) { - finished = 0; - return 0; - } - - domain = (unsigned int) - ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data; - op.cmd = DOM0_GETDOMAININFO; - - op.u.getdominfo.domain = domain; - - (void) HYPERVISOR_dom0_op(&op); - - end = snprintf(str, 256, "cpu: %lld\n", op.u.getdominfo.cpu_time); - - netop.cmd = NETWORK_OP_VIFQUERY; - netop.u.vif_query.domain = domain; - netop.u.vif_query.buf = vifs; - - (void) HYPERVISOR_network_op(&netop); - - for(i = 1; i <= vifs[0]; i++) { - netop.cmd = NETWORK_OP_VIFGETINFO; - netop.u.vif_getinfo.domain = domain; - netop.u.vif_getinfo.vif = vifs[i]; - - (void) HYPERVISOR_network_op(&netop); - - end += snprintf(str + end, 255 - end, - "vif%d: sent %lld bytes (%lld packets) " - "received %lld bytes (%lld packets)\n", - vifs[i], - netop.u.vif_getinfo.total_bytes_sent, - netop.u.vif_getinfo.total_packets_sent, - netop.u.vif_getinfo.total_bytes_received, - netop.u.vif_getinfo.total_packets_received); - } - - if (*off >= end + 1) return 0; - - copy_to_user(buff, str, end); - - finished = 1; - - return end + 1; -} - -static struct file_operations dom_usage_ops = { - read: dom_usage_read -}; - - -static void create_proc_dom_entries(int dom) -{ - struct proc_dir_entry * dir; - dom_procdata_t * dom_data; - char dir_name[16]; - struct proc_dir_entry * file; - - sprintf(dir_name, "dom%d", dom); - - dom_data = (dom_procdata_t *)kmalloc(sizeof(dom_procdata_t), GFP_KERNEL); - dom_data->domain = dom; - - dir = proc_mkdir(dir_name, xeno_base); - dir->data = dom_data; - - file = create_proc_entry("usage", 0600, dir); - if (file != NULL) + case IOCTL_PRIVCMD_HYPERCALL: { - file->owner = THIS_MODULE; - file->nlink = 1; - file->proc_fops = &dom_usage_ops; - file->data = (void *) dom; + privcmd_hypercall_t hypercall; + if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) + return -EFAULT; + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " + "movl 4(%%eax),%%ebx ;" + "movl 8(%%eax),%%ecx ;" + "movl 12(%%eax),%%edx ;" + "movl 16(%%eax),%%esi ;" + "movl 20(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + TRAP_INSTR "; " + "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); } + break; - file = create_proc_entry("phd", 0600, dir); - if (file != NULL) + case IOCTL_PRIVCMD_BLKMSG: { - file->owner = THIS_MODULE; - file->nlink = 1; - file->proc_fops = &dom0_phd_fops; - file->data = (void *) dom; + privcmd_blkmsg_t blkmsg; + char *kbuf; + int ret; + if ( copy_from_user(&blkmsg, (void *)data, sizeof(blkmsg)) ) + return -EFAULT; + if ( blkmsg.buf_size > PAGE_SIZE ) + return -EINVAL; + if ( (kbuf = kmalloc(blkmsg.buf_size, GFP_KERNEL)) == NULL ) + return -ENOMEM; + if ( copy_from_user(kbuf, blkmsg.buf, blkmsg.buf_size) ) { + kfree(kbuf); + return -EFAULT; + } + ret = xenolinux_control_msg((int)blkmsg.op, kbuf, blkmsg.buf_size); + if ( ret != 0 ) { + kfree(kbuf); + return ret; + } + if ( copy_to_user(blkmsg.buf, kbuf, blkmsg.buf_size) ) { + kfree(kbuf); + return -EFAULT; + } + kfree(kbuf); } -} - -/*********************************************************************** - * - * Implementation of /proc/xeno/domains - */ - -static dom0_op_t proc_domains_op; -static int proc_domains_finished; -static DECLARE_MUTEX(proc_xeno_domains_lock); - -static void *xeno_domains_next(struct seq_file *s, void *v, loff_t *pos) -{ - int ret; + break; + + case IOCTL_PRIVCMD_LINDEV_TO_XENDEV: + ret = (int)xldev_to_physdev((kdev_t)data); - if ( pos != NULL ) - ++(*pos); + case IOCTL_PRIVCMD_XENDEV_TO_LINDEV: + ret = (int)physdev_to_xldev((unsigned short)data); - if ( !proc_domains_finished ) + default: { - proc_domains_op.u.getdominfo.domain++; - ret = HYPERVISOR_dom0_op(&proc_domains_op); - if ( ret < 0 ) - proc_domains_finished = 1; + ret = -EINVAL; } - - return (proc_domains_finished) ? NULL : &proc_domains_op; -} - -static void *xeno_domains_start(struct seq_file *s, loff_t *ppos) -{ - loff_t pos = *ppos; - - down (&proc_xeno_domains_lock); - proc_domains_op.cmd = DOM0_GETDOMAININFO; - proc_domains_op.u.getdominfo.domain = 0; - (void)HYPERVISOR_dom0_op(&proc_domains_op); - proc_domains_finished = 0; - - while (pos > 0) { - pos --; - xeno_domains_next (s, NULL, NULL); + break; } - - return (proc_domains_finished) ? NULL : &proc_domains_op; -} -static void xeno_domains_stop(struct seq_file *s, void *v) -{ - up(&proc_xeno_domains_lock); + return ret; } -static int xeno_domains_show(struct seq_file *s, void *v) -{ - dom0_op_t *di = v; - - /* - * Output one domain's details to dom0. - * - * If you update this format string then change xi_list to match. - */ - - seq_printf (s, - "%8d %2d %1d %2d %8d %8ld %p %8d %s\n", - di -> u.getdominfo.domain, - di -> u.getdominfo.processor, - di -> u.getdominfo.has_cpu, - di -> u.getdominfo.state, - di -> u.getdominfo.hyp_events, - di -> u.getdominfo.mcu_advance, - (void *)di -> u.getdominfo.pg_head, - di -> u.getdominfo.tot_pages, - di -> u.getdominfo.name); - - return 0; -} -static struct seq_operations xeno_domains_op = { - .start = xeno_domains_start, - .next = xeno_domains_next, - .stop = xeno_domains_stop, - .show = xeno_domains_show, +static struct file_operations privcmd_file_ops = { + ioctl : privcmd_ioctl }; -static int xeno_domains_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &xeno_domains_op); -} - -static struct file_operations proc_xeno_domains_operations = { - open: xeno_domains_open, - read: seq_read, - llseek: seq_lseek, - release: seq_release, -}; - -/*********************************************************************** - * - * Implementation of /proc/xeno/dom0_cmd - */ - -static int dom0_cmd_write(struct file *file, const char *buffer, size_t size, - loff_t *off) -{ - dom0_op_t op; - - copy_from_user(&op, buffer, sizeof(dom0_op_t)); - - return HYPERVISOR_dom0_op(&op); -} - -static int handle_dom0_cmd_createdomain(unsigned long data) -{ - struct dom0_createdomain_args argbuf; - int namelen; - dom0_op_t op; - int ret; - - if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf))) - return -EFAULT; - - op.cmd = DOM0_CREATEDOMAIN; - op.u.newdomain.domain = -666; - op.u.newdomain.memory_kb = argbuf.kb_mem; - op.u.newdomain.num_vifs = 0; /* Not used anymore -- it's done in - BUILDDOMAIN. */ - namelen = strnlen_user(argbuf.name, MAX_DOMAIN_NAME); - if (copy_from_user(op.u.newdomain.name, argbuf.name, namelen + 1)) - return -EFAULT; - - /* Error checking? The old code deosn't appear to do any, and I - can't see where the return values are documented... */ - ret = HYPERVISOR_dom0_op(&op); - - if (op.u.newdomain.domain == -666) { - /* HACK: We use this to detect whether the create actually - succeeded, because Xen doesn't appear to want to tell us... */ - - /* The only time I've actually got this to happen was when trying - to create a domain with more memory than is actually in the - machine, so we guess the error code is ENOMEM. */ - return -ENOMEM; - } - - /* Create proc entries */ - ret = op.u.newdomain.domain; - create_proc_dom_entries(ret); - - return ret; -} - -static unsigned long handle_dom0_cmd_mapdommem(unsigned long data) -{ - struct dom0_mapdommem_args argbuf; - - if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf))) - return -EFAULT; - - return direct_mmap(argbuf.start_pfn << PAGE_SHIFT, - argbuf.tot_pages << PAGE_SHIFT, - PAGE_SHARED, - MAP_DISCONT, - argbuf.tot_pages); -} - -static int handle_dom0_cmd_unmapdommem(unsigned long data) -{ - struct dom0_unmapdommem_args argbuf; - - if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf))) - return -EFAULT; - - return direct_unmap(current->mm, argbuf.vaddr, - argbuf.tot_pages << PAGE_SHIFT); -} - -static int handle_dom0_cmd_dopgupdates(unsigned long data) -{ - struct dom0_dopgupdates_args argbuf; - struct list_head *entry; - direct_mmap_node_t *node; - - if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf))) - return -EFAULT; - - /* argbuf.pgt_update_arr had better be direct mapped... */ - /* Actually, we only *really* need to make sure that all of it's - pages are in memory and aren't going to get swapped out in the - mean time, but this is slightly easier than checking all of - that and is sufficient for the current userspace tools. */ - entry = find_direct(¤t->mm->context.direct_list, - argbuf.pgt_update_arr); - if (entry == ¤t->mm->context.direct_list) - return -EINVAL; - node = list_entry(entry, direct_mmap_node_t, list); - if (node->vm_start > argbuf.pgt_update_arr || - node->vm_end <= argbuf.pgt_update_arr * sizeof(page_update_request_t)) - return -EINVAL; - - return HYPERVISOR_pt_update((void *)argbuf.pgt_update_arr, - argbuf.num_pgt_updates); -} - -static int dom0_cmd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long data) -{ - switch (cmd) { - case IOCTL_DOM0_CREATEDOMAIN: - return handle_dom0_cmd_createdomain(data); - case IOCTL_DOM0_MAPDOMMEM: - return handle_dom0_cmd_mapdommem(data); - case IOCTL_DOM0_UNMAPDOMMEM: - return handle_dom0_cmd_unmapdommem(data); - case IOCTL_DOM0_DOPGUPDATES: - return handle_dom0_cmd_dopgupdates(data); - default: - return -ENOTTY; /* It isn't obvious why this is the correct error - code when an ioctl isn't recognised, but it - does appear to be what's used in the rest of - the kernel. */ - } -} - -/***********************************************************************/ - - -static struct file_operations dom0_cmd_file_ops = { - write : dom0_cmd_write, - ioctl : dom0_cmd_ioctl -}; static int __init init_module(void) { + if ( !(start_info.flags & SIF_PRIVILEGED) ) + return 0; + /* xeno proc root setup */ xeno_base = proc_mkdir("xeno", &proc_root); /* xeno control interface */ - dom0_cmd_intf = create_proc_entry("dom0_cmd", 0600, xeno_base); - - if ( dom0_cmd_intf != NULL ) + privcmd_intf = create_proc_entry("privcmd", 0400, xeno_base); + if ( privcmd_intf != NULL ) { - dom0_cmd_intf->owner = THIS_MODULE; - dom0_cmd_intf->nlink = 1; - dom0_cmd_intf->proc_fops = &dom0_cmd_file_ops; + privcmd_intf->owner = THIS_MODULE; + privcmd_intf->nlink = 1; + privcmd_intf->proc_fops = &privcmd_file_ops; } - /* domain list interface */ - dom_list_intf = create_proc_entry("domains", 0400, xeno_base); - if ( dom_list_intf != NULL ) - { - dom_list_intf->owner = THIS_MODULE; - dom_list_intf->nlink = 1; - dom_list_intf->proc_fops = &proc_xeno_domains_operations; - } - - /* set up /proc entries for dom 0 */ - create_proc_dom_entries(0); - return 0; } static void __exit cleanup_module(void) { - if ( dom0_cmd_intf == NULL ) return; - remove_proc_entry("dom0", &proc_root); - dom0_cmd_intf = NULL; + if ( privcmd_intf == NULL ) return; + remove_proc_entry("xeno", &proc_root); + privcmd_intf = NULL; } diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c deleted file mode 100644 index f36ac583c4..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "dom0_ops.h" - -#define MAP_CONT 0 -#define MAP_DISCONT 1 - -extern struct list_head * find_direct(struct list_head *, unsigned long); -extern int direct_remap_area_pages(struct mm_struct *, unsigned long, - unsigned long, unsigned long, pgprot_t); -extern void direct_zap_page_range(struct mm_struct *, unsigned long, - unsigned long); - -/* - * used for remapping discontiguous bits of domain's memory, pages to map are - * found from frame table beginning at the given first_pg index - */ -int direct_remap_disc_page_range(unsigned long from, - unsigned long first_pg, - int tot_pages, - pgprot_t prot) -{ - dom0_op_t dom0_op; - unsigned long *pfns = (unsigned long *)get_free_page(GFP_KERNEL); - unsigned long start = from; - int pages, i; - - while ( tot_pages != 0 ) - { - dom0_op.cmd = DOM0_GETMEMLIST; - dom0_op.u.getmemlist.start_pfn = first_pg; - pages = 1023; - dom0_op.u.getmemlist.num_pfns = 1024; - if ( tot_pages < 1024 ) - dom0_op.u.getmemlist.num_pfns = pages = tot_pages; - dom0_op.u.getmemlist.buffer = pfns; - (void)HYPERVISOR_dom0_op(&dom0_op); - first_pg = pfns[1023]; - - for ( i = 0; i < pages; i++ ) - { - if(direct_remap_area_pages(current->mm, - start, pfns[i] << PAGE_SHIFT, - PAGE_SIZE, prot)) - goto out; - start += PAGE_SIZE; - tot_pages--; - } - } - - out: - free_page((unsigned long)pfns); - return tot_pages; -} - - -unsigned long direct_mmap(unsigned long phys_addr, unsigned long size, - pgprot_t prot, int flag, int tot_pages) -{ - direct_mmap_node_t * dmmap; - struct list_head * entry; - unsigned long addr; - int ret = 0; - - if(!capable(CAP_SYS_ADMIN)){ - ret = -EPERM; - goto out; - } - - /* get unmapped area invokes xen specific arch_get_unmapped_area */ - addr = get_unmapped_area(NULL, 0, size, 0, 0); - if(addr & ~PAGE_MASK){ - ret = -ENOMEM; - goto out; - } - - /* add node on the list of directly mapped areas, make sure the - * list remains sorted. - */ - dmmap = (direct_mmap_node_t *)kmalloc(sizeof(direct_mmap_node_t), GFP_KERNEL); - dmmap->vm_start = addr; - dmmap->vm_end = addr + size; - entry = find_direct(¤t->mm->context.direct_list, addr); - if(entry != ¤t->mm->context.direct_list){ - list_add_tail(&dmmap->list, entry); - } else { - list_add_tail(&dmmap->list, ¤t->mm->context.direct_list); - } - - /* and perform the mapping */ - if(flag == MAP_DISCONT){ - ret = direct_remap_disc_page_range(addr, phys_addr >> PAGE_SHIFT, - tot_pages, prot); - } else { - ret = direct_remap_area_pages(current->mm, - addr, phys_addr, size, prot); - } - - if(ret == 0) - ret = addr; - - out: - return ret; -} - - -int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size) -{ - int count = 0, tot_pages = (size+PAGE_SIZE-1) >> PAGE_SHIFT; - direct_mmap_node_t * node; - struct list_head * curr; - struct list_head * direct_list = &mm->context.direct_list; - - curr = direct_list->next; - while ( curr != direct_list ) - { - node = list_entry(curr, direct_mmap_node_t, list); - if ( node->vm_start == addr ) - break; - curr = curr->next; - } - - if ( curr == direct_list ) - return -1; - - list_del(&node->list); - kfree(node); - - while ( count < tot_pages ) - { - direct_zap_page_range(mm, addr, PAGE_SIZE); - addr += PAGE_SIZE; - count++; - } - - return 0; -} diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h deleted file mode 100644 index 23006eae0d..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * dom0_ops.h - * - * Process command requests from domain-0 guest OS. - * This file includes the Xen part of the interface, plus the extra stuff - * that is dealt with by Xenolinux without being handed down to Xen. - * - * Copyright (c) 2002-2003, K A Fraser, B Dragovic - */ - -#ifndef __DOM0_DOM0_OPS_H__ -#define __DOM0_DOM0_OPS_H__ - -/* External users of this header file will include Xen's version separately. */ -#ifdef __KERNEL__ -#define NO_DOM0_OP_T -#include -#endif - -/* Extra commands dealt with by Xenolinux. */ -#define MAP_DOM_MEM 1014 -#define DO_PGUPDATES 1015 - -typedef struct dom_mem -{ - unsigned int domain; - unsigned long vaddr; - unsigned long start_pfn; - int tot_pages; -} dom_mem_t; - -typedef struct dom_pgupdate -{ - unsigned long pgt_update_arr; - unsigned long num_pgt_updates; -} dom_pgupdate_t; - -typedef struct dom0_op_st -{ - unsigned long cmd; - union - { - dom0_newdomain_t newdomain; - dom0_killdomain_t killdomain; - dom0_getmemlist_t getmemlist; - dom0_bvtctl_t bvtctl; - dom0_adjustdom_t adjustdom; - dom_mem_t dommem; - dom_pgupdate_t pgupdate; - dom_meminfo_t meminfo; - dom0_getdominfo_t getdominfo; - dom0_iopl_t iopl; - } u; -} dom0_op_t; - -#endif /* __DOM0_DOM0_OPS_H__ */ diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c deleted file mode 100644 index 9c5fce7857..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- - **************************************************************************** - * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge - **************************************************************************** - * - * File: sched_ops.c - * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) - * Changes: - * - * Date: Mar 2003 - * - * Environment: XenoLinux - * Description: Dom0 Control interface to scheduler in Xen - * - * code based on Andy's vfr parsing code - * - * Commands understood by the interface: - * - * C - * S - * - **************************************************************************** - * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $ - **************************************************************************** - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dom0_ops.h" - -#define SCHED_ENTRY "sched" -extern struct proc_dir_entry *xeno_base; -static struct proc_dir_entry *sched_pde; - -static unsigned char readbuf[1024]; - -static int sched_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - strcpy(page, readbuf); - *readbuf = '\0'; - *eof = 1; - *start = page; - return strlen(page); -} - - -static int sched_write_proc(struct file *file, const char *buffer, - u_long count, void *data) -{ - dom0_op_t op; - - int ret, len; - int ts, te, tl; /* token start, end, and length */ - - /* Only admin can adjust scheduling parameters */ - if ( !capable(CAP_SYS_ADMIN) ) - return -EPERM; - - /* parse the commands */ - len = count; - ts = te = 0; - - while ( count && isspace(buffer[ts]) ) { ts++; count--; } /*skip spaces*/ - te = ts; - while ( count && !isspace(buffer[te]) ) { te++; count--; } /*command end*/ - if ( te <= ts ) goto bad; - tl = te - ts; - - if ( strncmp(&buffer[ts], "C", tl) == 0 ) { - op.cmd = DOM0_BVTCTL; - } else if ( strncmp(&buffer[ts], "S", tl) == 0 ) { - op.cmd = DOM0_ADJUSTDOM; - } else - goto bad; - - /* skip whitspaces and get first parameter */ - ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; } - te = ts; while ( count && !isspace(buffer[te]) ) { te++; count--; } - if ( te <= ts ) goto bad; - tl = te - ts; - if ( !isdigit(buffer[ts]) ) goto bad; - - if (op.cmd == DOM0_BVTCTL) { - /* get context switch allowance */ - sscanf(&buffer[ts], "%lu", &op.u.bvtctl.ctx_allow); - } else if (op.cmd == DOM0_ADJUSTDOM) { - sscanf(&buffer[ts], "%u %lu %lu %lu %lu", - &op.u.adjustdom.domain, - &op.u.adjustdom.mcu_adv, - &op.u.adjustdom.warp, - &op.u.adjustdom.warpl, - &op.u.adjustdom.warpu); - } - ret = HYPERVISOR_dom0_op(&op); - return sizeof(op); - - bad: - return -EINVAL; - -} - - -/* - * main scheduler interface driver driver initialization function. - */ -static int __init init_module(void) -{ - printk(KERN_ALERT "Starting Domain Scheduler Control Interface\n"); - - sched_pde = create_proc_entry(SCHED_ENTRY, 0600, xeno_base); - if ( sched_pde == NULL ) - { - printk(KERN_ALERT "Unable to create dom scheduler proc entry!"); - return -1; - } - - sched_pde->read_proc = sched_read_proc; - sched_pde->write_proc = sched_write_proc; - - return 0; -} - -static void __exit cleanup_module(void) -{ -} - -module_init(init_module); -module_exit(cleanup_module); - diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c index 852f6943e2..2091464169 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c @@ -224,7 +224,7 @@ static int vfr_write_proc(struct file *file, const char *buffer, static int __init init_module(void) { *readbuf = '\0'; - proc_vfr = create_proc_entry ("vfr", 0600, &proc_root); + proc_vfr = create_proc_entry ("xeno/vfr", 0600, &proc_root); if ( proc_vfr != NULL ) { proc_vfr->owner = THIS_MODULE; @@ -239,7 +239,7 @@ static int __init init_module(void) static void __exit cleanup_module(void) { if ( proc_vfr == NULL ) return; - remove_proc_entry("vfr", &proc_root); + remove_proc_entry("xeno/vfr", &proc_root); proc_vfr = NULL; } diff --git a/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c b/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c index 6798d5259f..3b17c7326c 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c @@ -145,9 +145,6 @@ void release_segments(struct mm_struct *mm) flush_page_update_queue(); vfree(ldt); } - - /* YUK! We do this here because destroy_context() is too late. */ - destroy_direct_list(mm); } /* diff --git a/xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile b/xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile index 79c93767fd..d0d16114b6 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile +++ b/xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile @@ -9,7 +9,7 @@ O_TARGET := mm.o -obj-y := init.o fault.o extable.o pageattr.o hypervisor.o get_unmapped_area.o ioremap.o +obj-y := init.o fault.o extable.o pageattr.o hypervisor.o ioremap.o export-objs := pageattr.o diff --git a/xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c b/xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c deleted file mode 100644 index 2258d0160b..0000000000 --- a/xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c +++ /dev/null @@ -1,114 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -extern int direct_unmap(struct mm_struct *, unsigned long, unsigned long); - -int init_direct_list(struct mm_struct *mm) -{ - INIT_LIST_HEAD(&mm->context.direct_list); - return 0; -} - - -void destroy_direct_list(struct mm_struct *mm) -{ - struct list_head *curr, *direct_list = &mm->context.direct_list; - while ( (curr = direct_list->next) != direct_list ) - { - direct_mmap_node_t *node = list_entry(curr, direct_mmap_node_t, list); - if ( direct_unmap(mm, node->vm_start, node->vm_end - node->vm_start) ) - BUG(); - } -} - - -struct list_head *find_direct(struct list_head *list, unsigned long addr) -{ - struct list_head * curr; - struct list_head * direct_list = ¤t->mm->context.direct_list; - direct_mmap_node_t * node; - - for ( curr = direct_list->next; curr != direct_list; curr = curr->next ) - { - node = list_entry(curr, direct_mmap_node_t, list); - if ( node->vm_start >= addr ) break; - } - - return curr; -} - - -unsigned long arch_get_unmapped_area(struct file *filp, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ - struct vm_area_struct *vma; - direct_mmap_node_t * node; - struct list_head * curr; - struct list_head * direct_list = ¤t->mm->context.direct_list; - - if ( len > TASK_SIZE ) - return -ENOMEM; - - if ( addr ) - { - addr = PAGE_ALIGN(addr); - vma = find_vma(current->mm, addr); - curr = find_direct(direct_list, addr); - node = list_entry(curr, direct_mmap_node_t, list); - if ( (TASK_SIZE - len >= addr) && - (!vma || addr + len <= vma->vm_start) && - ((curr == direct_list) || addr + len <= node->vm_start) ) - return addr; - } - - addr = PAGE_ALIGN(TASK_UNMAPPED_BASE); - - - /* Find first VMA and direct_map nodes with vm_start > addr */ - vma = find_vma(current->mm, addr); - curr = find_direct(direct_list, addr); - node = list_entry(curr, direct_mmap_node_t, list); - - for ( ; ; ) - { - if ( TASK_SIZE - len < addr ) return -ENOMEM; - - if ( vma && ((curr == direct_list) || - (vma->vm_start < node->vm_start)) ) - { - /* Do we fit before VMA node? */ - if ( addr + len <= vma->vm_start ) return addr; - addr = vma->vm_end; - vma = vma->vm_next; - } - else if ( curr != direct_list ) - { - /* Do we fit before direct_map node? */ - if ( addr + len <= node->vm_start) return addr; - addr = node->vm_end; - curr = curr->next; - node = list_entry(curr, direct_mmap_node_t, list); - } - else - { - /* !vma && curr == direct_list */ - return addr; - } - } -} diff --git a/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c b/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c index f7c6fad278..db0221d2dd 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c @@ -18,10 +18,10 @@ #include #include +#if defined(CONFIG_XENO_PRIV) + #define direct_set_pte(pteptr, pteval) \ queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, (pteval).pte_low) -#define direct_pte_clear(pteptr) \ - queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, 0) #define __direct_pte(x) ((pte_t) { (x) } ) #define __direct_mk_pte(page_nr,pgprot) \ __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot)) @@ -29,9 +29,6 @@ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot) - -/******************* Mapping a page range directly ************************/ - static inline void direct_remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, @@ -51,7 +48,7 @@ static inline void direct_remap_area_pte(pte_t *pte, printk("direct_remap_area_pte: page already exists\n"); BUG(); } - direct_set_pte(pte, direct_mk_pte_phys(machine_addr, prot)); + direct_set_pte(pte, pte_mkio(direct_mk_pte_phys(machine_addr, prot))); address += PAGE_SIZE; machine_addr += PAGE_SIZE; pte++; @@ -119,105 +116,9 @@ int direct_remap_area_pages(struct mm_struct *mm, return error; } +#endif /* CONFIG_XENO_PRIV */ -/************************ Zapping a page range directly *******************/ - -static inline int direct_zap_pte_range(mmu_gather_t *tlb, - pmd_t * pmd, - unsigned long address, - unsigned long size) -{ - unsigned long offset; - pte_t * ptep; - int freed = 0; - - if (pmd_none(*pmd)) - return 0; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - return 0; - } - ptep = pte_offset(pmd, address); - offset = address & ~PMD_MASK; - if (offset + size > PMD_SIZE) - size = PMD_SIZE - offset; - size &= PAGE_MASK; - for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) { - pte_t pte = *ptep; - if (pte_none(pte)) - continue; - freed++; - direct_pte_clear(ptep); - } - - return freed; -} - -static inline int direct_zap_pmd_range(mmu_gather_t *tlb, - pgd_t * dir, - unsigned long address, - unsigned long size) -{ - pmd_t * pmd; - unsigned long end; - int freed; - - if (pgd_none(*dir)) - return 0; - if (pgd_bad(*dir)) { - pgd_ERROR(*dir); - pgd_clear(dir); - return 0; - } - pmd = pmd_offset(dir, address); - end = address + size; - if (end > ((address + PGDIR_SIZE) & PGDIR_MASK)) - end = ((address + PGDIR_SIZE) & PGDIR_MASK); - freed = 0; - do { - freed += direct_zap_pte_range(tlb, pmd, address, end - address); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return freed; -} - -void direct_zap_page_range(struct mm_struct *mm, - unsigned long address, - unsigned long size) -{ - mmu_gather_t *tlb; - pgd_t * dir; - unsigned long start = address, end = address + size; - int freed = 0; - - dir = pgd_offset(mm, address); - - if (address >= end) - BUG(); - spin_lock(&mm->page_table_lock); - flush_cache_range(mm, address, end); - tlb = tlb_gather_mmu(mm); - - do { - freed += direct_zap_pmd_range(tlb, dir, address, end - address); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - - /* this will flush any remaining tlb entries */ - tlb_finish_mmu(tlb, start, end); - - /* decrementing rss removed */ - spin_unlock(&mm->page_table_lock); -} - - - -/****************** Generic public functions ****************************/ - /* * Remap an arbitrary machine address space into the kernel virtual * address space. Needed when a privileged instance of Xenolinux wants @@ -231,6 +132,7 @@ void * __ioremap(unsigned long machine_addr, unsigned long size, unsigned long flags) { +#if defined(CONFIG_XENO_PRIV) void * addr; struct vm_struct * area; unsigned long offset, last_addr; @@ -255,45 +157,22 @@ void * __ioremap(unsigned long machine_addr, if (!area) return NULL; addr = area->addr; - prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | - flags); + prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | + _PAGE_ACCESSED | flags); if (direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(addr), machine_addr, size, prot)) { vfree(addr); return NULL; } return (void *) (offset + (char *)addr); +#else + return NULL; +#endif } -/* - * 'vfree' is basically inlined here. This is because we use a different - * function to zap the associated page range. - */ void iounmap(void *addr) { - struct vm_struct **p, *tmp; - - addr = (void *)((unsigned long)addr & PAGE_MASK); - - if (addr == NULL) - return; - - write_lock(&vmlist_lock); - - for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { - if (tmp->addr == addr) { - *p = tmp->next; - direct_zap_page_range(&init_mm, - VMALLOC_VMADDR(tmp->addr), - tmp->size); - write_unlock(&vmlist_lock); - kfree(tmp); - return; - } - } - - write_unlock(&vmlist_lock); - printk(KERN_ERR "Trying to iounmap() nonexistent vm area (%p)\n", addr); + vfree((void *)((unsigned long)addr & PAGE_MASK)); } diff --git a/xenolinux-2.4.21-sparse/drivers/char/mem.c b/xenolinux-2.4.21-sparse/drivers/char/mem.c new file mode 100644 index 0000000000..bb0ab61f3f --- /dev/null +++ b/xenolinux-2.4.21-sparse/drivers/char/mem.c @@ -0,0 +1,807 @@ +/* + * linux/drivers/char/mem.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Added devfs support. + * Jan-11-1998, C. Scott Ananian + * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar + * + * MODIFIED FOR XENOLINUX by Keir Fraser, 10th July 2003. + * Xenolinux has strange semantics for /dev/mem and /dev/kmem!! + * 1. mmap will not work on /dev/kmem + * 2. mmap on /dev/mem interprets the 'file offset' as a machine address + * rather than a physical address. + * I don't believe anyone sane mmaps /dev/kmem, but /dev/mem is mmapped + * to get at memory-mapped I/O spaces (eg. the VESA X server does this). + * For this to work at all we need to expect machine addresses. + * Reading/writing of /dev/kmem expects kernel virtual addresses, as usual. + * Reading/writing of /dev/mem expects 'physical addresses' as usual -- this + * is because /dev/mem can only read/write existing kernel mappings, which + * will be normal RAM, and we should present pseudo-physical layout for all + * except I/O (which is the sticky case that mmap is hacked to deal with). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_I2C +extern int i2c_init_all(void); +#endif +#ifdef CONFIG_FB +extern void fbmem_init(void); +#endif +#ifdef CONFIG_PROM_CONSOLE +extern void prom_con_init(void); +#endif +#ifdef CONFIG_MDA_CONSOLE +extern void mda_console_init(void); +#endif +#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) +extern void tapechar_init(void); +#endif + +static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, + const char * buf, size_t count, loff_t *ppos) +{ + ssize_t written; + + written = 0; +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ + if (realp < PAGE_SIZE) { + unsigned long sz = PAGE_SIZE-realp; + if (sz > count) sz = count; + /* Hmm. Do something? */ + buf+=sz; + p+=sz; + count-=sz; + written+=sz; + } +#endif + if (copy_from_user(p, buf, count)) + return -EFAULT; + written += count; + *ppos += written; + return written; +} + + +/* + * This funcion reads the *physical* memory. The f_pos points directly to the + * memory location. + */ +static ssize_t read_mem(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + unsigned long end_mem; + ssize_t read; + + end_mem = __pa(high_memory); + if (p >= end_mem) + return 0; + if (count > end_mem - p) + count = end_mem - p; + read = 0; +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ + if (p < PAGE_SIZE) { + unsigned long sz = PAGE_SIZE-p; + if (sz > count) + sz = count; + if (sz > 0) { + if (clear_user(buf, sz)) + return -EFAULT; + buf += sz; + p += sz; + count -= sz; + read += sz; + } + } +#endif + if (copy_to_user(buf, __va(p), count)) + return -EFAULT; + read += count; + *ppos += read; + return read; +} + +static ssize_t write_mem(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + unsigned long end_mem; + + end_mem = __pa(high_memory); + if (p >= end_mem) + return 0; + if (count > end_mem - p) + count = end_mem - p; + return do_write_mem(file, __va(p), p, buf, count, ppos); +} + +#ifndef pgprot_noncached + +/* + * This should probably be per-architecture in + */ +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + +#if defined(__i386__) || defined(__x86_64__) + /* On PPro and successors, PCD alone doesn't always mean + uncached because of interactions with the MTRRs. PCD | PWT + means definitely uncached. */ + if (boot_cpu_data.x86 > 3) + prot |= _PAGE_PCD | _PAGE_PWT; +#elif defined(__powerpc__) + prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; +#elif defined(__mc68000__) +#ifdef SUN3_PAGE_NOCACHE + if (MMU_IS_SUN3) + prot |= SUN3_PAGE_NOCACHE; + else +#endif + if (MMU_IS_851 || MMU_IS_030) + prot |= _PAGE_NOCACHE030; + /* Use no-cache mode, serialized */ + else if (MMU_IS_040 || MMU_IS_060) + prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S; +#endif + + return __pgprot(prot); +} + +#endif /* !pgprot_noncached */ + +/* + * Architectures vary in how they handle caching for addresses + * outside of main memory. + */ +static inline int noncached_address(unsigned long addr) +{ +#if defined(__i386__) + /* + * On the PPro and successors, the MTRRs are used to set + * memory types for physical addresses outside main memory, + * so blindly setting PCD or PWT on those pages is wrong. + * For Pentiums and earlier, the surround logic should disable + * caching for the high addresses through the KEN pin, but + * we maintain the tradition of paranoia in this code. + */ + return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) + && addr >= __pa(high_memory); +#else + return addr >= __pa(high_memory); +#endif +} + +static int mmap_mem(struct file * file, struct vm_area_struct * vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + +#if defined(CONFIG_XENO) && defined(CONFIG_XENO_PRIV) + if (!(start_info.flags & SIF_PRIVILEGED)) + return -ENXIO; + + /* DONTCOPY is essential for Xenolinux as copy_page_range is broken. */ + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + if (direct_remap_area_pages(vma->vm_mm, vma->vm_start, offset, + vma->vm_end-vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + return 0; +#elif defined(CONFIG_XENO) + return -ENXIO; +#else + /* + * Accessing memory above the top the kernel knows about or + * through a file pointer that was marked O_SYNC will be + * done non-cached. + */ + if (noncached_address(offset) || (file->f_flags & O_SYNC)) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* Don't try to swap out physical pages.. */ + vma->vm_flags |= VM_RESERVED; + + /* + * Don't dump addresses that are not real memory to a core file. + */ + if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) + vma->vm_flags |= VM_IO; + + if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + return 0; +#endif +} + +/* + * This function reads the *virtual* memory as seen by the kernel. + */ +static ssize_t read_kmem(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + ssize_t read = 0; + ssize_t virtr = 0; + char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ + + if (p < (unsigned long) high_memory) { + read = count; + if (count > (unsigned long) high_memory - p) + read = (unsigned long) high_memory - p; + +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ + if (p < PAGE_SIZE && read > 0) { + size_t tmp = PAGE_SIZE - p; + if (tmp > read) tmp = read; + if (clear_user(buf, tmp)) + return -EFAULT; + buf += tmp; + p += tmp; + read -= tmp; + count -= tmp; + } +#endif + if (copy_to_user(buf, (char *)p, read)) + return -EFAULT; + p += read; + buf += read; + count -= read; + } + + if (count > 0) { + kbuf = (char *)__get_free_page(GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + while (count > 0) { + int len = count; + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + len = vread(kbuf, (char *)p, len); + if (!len) + break; + if (copy_to_user(buf, kbuf, len)) { + free_page((unsigned long)kbuf); + return -EFAULT; + } + count -= len; + buf += len; + virtr += len; + p += len; + } + free_page((unsigned long)kbuf); + } + *ppos = p; + return virtr + read; +} + +extern long vwrite(char *buf, char *addr, unsigned long count); + +/* + * This function writes to the *virtual* memory as seen by the kernel. + */ +static ssize_t write_kmem(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + ssize_t wrote = 0; + ssize_t virtr = 0; + char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + + if (p < (unsigned long) high_memory) { + wrote = count; + if (count > (unsigned long) high_memory - p) + wrote = (unsigned long) high_memory - p; + + wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos); + + p += wrote; + buf += wrote; + count -= wrote; + } + + if (count > 0) { + kbuf = (char *)__get_free_page(GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + while (count > 0) { + int len = count; + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + if (len && copy_from_user(kbuf, buf, len)) { + free_page((unsigned long)kbuf); + return -EFAULT; + } + len = vwrite(kbuf, (char *)p, len); + count -= len; + buf += len; + virtr += len; + p += len; + } + free_page((unsigned long)kbuf); + } + + *ppos = p; + return virtr + wrote; +} + +#if defined(CONFIG_ISA) || !defined(__mc68000__) +static ssize_t read_port(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + unsigned long i = *ppos; + char *tmp = buf; + + if (verify_area(VERIFY_WRITE,buf,count)) + return -EFAULT; + while (count-- > 0 && i < 65536) { + if (__put_user(inb(i),tmp) < 0) + return -EFAULT; + i++; + tmp++; + } + *ppos = i; + return tmp-buf; +} + +static ssize_t write_port(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long i = *ppos; + const char * tmp = buf; + + if (verify_area(VERIFY_READ,buf,count)) + return -EFAULT; + while (count-- > 0 && i < 65536) { + char c; + if (__get_user(c, tmp)) + return -EFAULT; + outb(c,i); + i++; + tmp++; + } + *ppos = i; + return tmp-buf; +} +#endif + +static ssize_t read_null(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + return 0; +} + +static ssize_t write_null(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + return count; +} + +/* + * For fun, we are using the MMU for this. + */ +static inline size_t read_zero_pagealigned(char * buf, size_t size) +{ + struct mm_struct *mm; + struct vm_area_struct * vma; + unsigned long addr=(unsigned long)buf; + + mm = current->mm; + /* Oops, this was forgotten before. -ben */ + down_read(&mm->mmap_sem); + + /* For private mappings, just map in zero pages. */ + for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { + unsigned long count; + + if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) + goto out_up; + if (vma->vm_flags & VM_SHARED) + break; +#if defined(CONFIG_XENO_PRIV) + if (vma->vm_flags & VM_IO) + break; +#endif + count = vma->vm_end - addr; + if (count > size) + count = size; + + zap_page_range(mm, addr, count); + zeromap_page_range(addr, count, PAGE_COPY); + + size -= count; + buf += count; + addr += count; + if (size == 0) + goto out_up; + } + + up_read(&mm->mmap_sem); + + /* The shared case is hard. Let's do the conventional zeroing. */ + do { + unsigned long unwritten = clear_user(buf, PAGE_SIZE); + if (unwritten) + return size + unwritten - PAGE_SIZE; + if (current->need_resched) + schedule(); + buf += PAGE_SIZE; + size -= PAGE_SIZE; + } while (size); + + return size; +out_up: + up_read(&mm->mmap_sem); + return size; +} + +static ssize_t read_zero(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + unsigned long left, unwritten, written = 0; + + if (!count) + return 0; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + left = count; + + /* do we want to be clever? Arbitrary cut-off */ + if (count >= PAGE_SIZE*4) { + unsigned long partial; + + /* How much left of the page? */ + partial = (PAGE_SIZE-1) & -(unsigned long) buf; + unwritten = clear_user(buf, partial); + written = partial - unwritten; + if (unwritten) + goto out; + left -= partial; + buf += partial; + unwritten = read_zero_pagealigned(buf, left & PAGE_MASK); + written += (left & PAGE_MASK) - unwritten; + if (unwritten) + goto out; + buf += left & PAGE_MASK; + left &= ~PAGE_MASK; + } + unwritten = clear_user(buf, left); + written += left - unwritten; +out: + return written ? written : -EFAULT; +} + +static int mmap_zero(struct file * file, struct vm_area_struct * vma) +{ + if (vma->vm_flags & VM_SHARED) + return shmem_zero_setup(vma); + if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + return 0; +} + +static ssize_t write_full(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + return -ENOSPC; +} + +/* + * Special lseek() function for /dev/null and /dev/zero. Most notably, you + * can fopen() both devices with "a" now. This was previously impossible. + * -- SRB. + */ + +static loff_t null_lseek(struct file * file, loff_t offset, int orig) +{ + return file->f_pos = 0; +} + +/* + * The memory devices use the full 32/64 bits of the offset, and so we cannot + * check against negative addresses: they are ok. The return value is weird, + * though, in that case (0). + * + * also note that seeking relative to the "end of file" isn't supported: + * it has no meaning, so it returns -EINVAL. + */ +static loff_t memory_lseek(struct file * file, loff_t offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + return file->f_pos; + case 1: + file->f_pos += offset; + return file->f_pos; + default: + return -EINVAL; + } +} + +static int open_port(struct inode * inode, struct file * filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +struct page *kmem_vm_nopage(struct vm_area_struct *vma, unsigned long address, int write) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long kaddr; + pgd_t *pgd; + pmd_t *pmd; + pte_t *ptep, pte; + struct page *page = NULL; + + /* address is user VA; convert to kernel VA of desired page */ + kaddr = (address - vma->vm_start) + offset; + kaddr = VMALLOC_VMADDR(kaddr); + + spin_lock(&init_mm.page_table_lock); + + /* Lookup page structure for kernel VA */ + pgd = pgd_offset(&init_mm, kaddr); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + goto out; + pmd = pmd_offset(pgd, kaddr); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + goto out; + ptep = pte_offset(pmd, kaddr); + if (!ptep) + goto out; + pte = *ptep; + if (!pte_present(pte)) + goto out; + if (write && !pte_write(pte)) + goto out; + page = pte_page(pte); + if (!VALID_PAGE(page)) { + page = NULL; + goto out; + } + + /* Increment reference count on page */ + get_page(page); + +out: + spin_unlock(&init_mm.page_table_lock); + + return page; +} + +struct vm_operations_struct kmem_vm_ops = { + nopage: kmem_vm_nopage, +}; + +static int mmap_kmem(struct file * file, struct vm_area_struct * vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + +#if defined(CONFIG_XENO) + return -ENXIO; +#endif + + /* + * If the user is not attempting to mmap a high memory address then + * the standard mmap_mem mechanism will work. High memory addresses + * need special handling, as remap_page_range expects a physically- + * contiguous range of kernel addresses (such as obtained in kmalloc). + */ + if ((offset + size) < (unsigned long) high_memory) + return mmap_mem(file, vma); + + /* + * Accessing memory above the top the kernel knows about or + * through a file pointer that was marked O_SYNC will be + * done non-cached. + */ + if (noncached_address(offset) || (file->f_flags & O_SYNC)) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* Don't do anything here; "nopage" will fill the holes */ + vma->vm_ops = &kmem_vm_ops; + + /* Don't try to swap out physical pages.. */ + vma->vm_flags |= VM_RESERVED; + + /* + * Don't dump addresses that are not real memory to a core file. + */ + vma->vm_flags |= VM_IO; + + return 0; +} + +#define zero_lseek null_lseek +#define full_lseek null_lseek +#define write_zero write_null +#define read_full read_zero +#define open_mem open_port +#define open_kmem open_mem + +static struct file_operations mem_fops = { + llseek: memory_lseek, + read: read_mem, + write: write_mem, + mmap: mmap_mem, + open: open_mem, +}; + +static struct file_operations kmem_fops = { + llseek: memory_lseek, + read: read_kmem, + write: write_kmem, + mmap: mmap_kmem, + open: open_kmem, +}; + +static struct file_operations null_fops = { + llseek: null_lseek, + read: read_null, + write: write_null, +}; + +#if defined(CONFIG_ISA) || !defined(__mc68000__) +static struct file_operations port_fops = { + llseek: memory_lseek, + read: read_port, + write: write_port, + open: open_port, +}; +#endif + +static struct file_operations zero_fops = { + llseek: zero_lseek, + read: read_zero, + write: write_zero, + mmap: mmap_zero, +}; + +static struct file_operations full_fops = { + llseek: full_lseek, + read: read_full, + write: write_full, +}; + +static int memory_open(struct inode * inode, struct file * filp) +{ + switch (MINOR(inode->i_rdev)) { + case 1: + filp->f_op = &mem_fops; + break; + case 2: + filp->f_op = &kmem_fops; + break; + case 3: + filp->f_op = &null_fops; + break; +#if defined(CONFIG_ISA) || !defined(__mc68000__) + case 4: +#if defined(CONFIG_XENO) +#if defined(CONFIG_XENO_PRIV) + if (!(start_info.flags & SIF_PRIVILEGED)) +#endif + return -ENXIO; +#endif + filp->f_op = &port_fops; + break; +#endif + case 5: + filp->f_op = &zero_fops; + break; + case 7: + filp->f_op = &full_fops; + break; + case 8: + filp->f_op = &random_fops; + break; + case 9: + filp->f_op = &urandom_fops; + break; + default: + return -ENXIO; + } + if (filp->f_op && filp->f_op->open) + return filp->f_op->open(inode,filp); + return 0; +} + +void __init memory_devfs_register (void) +{ + /* These are never unregistered */ + static const struct { + unsigned short minor; + char *name; + umode_t mode; + struct file_operations *fops; + } list[] = { /* list of minor devices */ + {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, + {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, + {3, "null", S_IRUGO | S_IWUGO, &null_fops}, +#if defined(CONFIG_ISA) || !defined(__mc68000__) + {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, +#endif + {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, + {7, "full", S_IRUGO | S_IWUGO, &full_fops}, + {8, "random", S_IRUGO | S_IWUSR, &random_fops}, + {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops} + }; + int i; + + for (i=0; i<(sizeof(list)/sizeof(*list)); i++) + devfs_register (NULL, list[i].name, DEVFS_FL_NONE, + MEM_MAJOR, list[i].minor, + list[i].mode | S_IFCHR, + list[i].fops, NULL); +} + +static struct file_operations memory_fops = { + open: memory_open, /* just a selector for the real open */ +}; + +int __init chr_dev_init(void) +{ + if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops)) + printk("unable to get major %d for memory devs\n", MEM_MAJOR); + memory_devfs_register(); + rand_initialize(); +#ifdef CONFIG_I2C + i2c_init_all(); +#endif +#if defined (CONFIG_FB) + fbmem_init(); +#endif +#if defined (CONFIG_PROM_CONSOLE) + prom_con_init(); +#endif +#if defined (CONFIG_MDA_CONSOLE) + mda_console_init(); +#endif + tty_init(); +#ifdef CONFIG_M68K_PRINTER + lp_m68k_init(); +#endif + misc_init(); +#if CONFIG_QIC02_TAPE + qic02_tape_init(); +#endif +#ifdef CONFIG_FTAPE + ftape_init(); +#endif +#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) + tapechar_init(); +#endif + return 0; +} + +__initcall(chr_dev_init); diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h b/xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h deleted file mode 100644 index 6609be0ae2..0000000000 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h +++ /dev/null @@ -1,36 +0,0 @@ -/* IOCTLs used when access /proc/xeno/dom0_cmd. */ -#ifndef __DOM0_H__ -#define __DOM0_H__ - -#define IOCTL_DOM0_CREATEDOMAIN _IOC(_IOC_READ, 'x', 0, sizeof(struct dom0_createdomain_args)) -#define IOCTL_DOM0_MAPDOMMEM _IOC(_IOC_READ, 'x', 1, sizeof(struct dom0_mapdommem_args)) -#define IOCTL_DOM0_UNMAPDOMMEM _IOC(_IOC_READ, 'x', 2, sizeof(struct dom0_unmapdommem_args)) -#define IOCTL_DOM0_DOPGUPDATES _IOC(_IOC_READ, 'x', 3, sizeof(struct dom0_dopgupdates_args)) - -struct dom0_createdomain_args -{ - unsigned int kb_mem; - const char *name; -}; - -struct dom0_mapdommem_args -{ - unsigned int domain; - unsigned start_pfn; - unsigned tot_pages; -}; - -struct dom0_unmapdommem_args -{ - unsigned long vaddr; - unsigned long start_pfn; - unsigned long tot_pages; -}; - -struct dom0_dopgupdates_args -{ - unsigned long pgt_update_arr; - unsigned long num_pgt_updates; -}; - -#endif /* __DOM0_H__ */ diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h index abf109b2ca..751bdc7888 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h @@ -9,9 +9,9 @@ #ifndef __HYPERVISOR_H__ #define __HYPERVISOR_H__ +#include #include #include -//#include /* arch/xeno/kernel/setup.c */ union start_info_union diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h b/xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h deleted file mode 100644 index b7bc05d808..0000000000 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __i386_MMU_H -#define __i386_MMU_H - -#include - -/* describes dirrectly mapped vma nodes */ -typedef struct { - struct list_head list; - unsigned long vm_start; - unsigned long vm_end; -} direct_mmap_node_t; - -/* - * The i386 doesn't have a mmu context, but - * we put the segment information here. - */ -typedef struct { - void *segments; - unsigned long cpuvalid; - struct list_head direct_list; -} mm_context_t; - -#endif diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h b/xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h index 83514ebd14..1eab441990 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h @@ -5,15 +5,12 @@ #include #include #include -#include - -/* Hooked directly from 'init_new_context'. */ -extern int init_direct_list(struct mm_struct *); -/* Called from 'release_segments'. */ -extern void destroy_direct_list(struct mm_struct *); +/* + * possibly do the LDT unload here? + */ #define destroy_context(mm) do { } while(0) -#define init_new_context(tsk,mm) init_direct_list(mm) +#define init_new_context(tsk,mm) 0 #ifdef CONFIG_SMP diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h b/xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h index 27126dcaac..f0ea5c3a66 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h @@ -35,6 +35,45 @@ static inline void queue_multicall2( nr_multicall_ents = i+1; } +static inline void queue_multicall3( + unsigned long op, unsigned long arg1, unsigned long arg2, + unsigned long arg3) +{ + int i = nr_multicall_ents; + multicall_list[i].op = op; + multicall_list[i].args[0] = arg1; + multicall_list[i].args[1] = arg2; + multicall_list[i].args[2] = arg3; + nr_multicall_ents = i+1; +} + +static inline void queue_multicall4( + unsigned long op, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4) +{ + int i = nr_multicall_ents; + multicall_list[i].op = op; + multicall_list[i].args[0] = arg1; + multicall_list[i].args[1] = arg2; + multicall_list[i].args[2] = arg3; + multicall_list[i].args[3] = arg4; + nr_multicall_ents = i+1; +} + +static inline void queue_multicall5( + unsigned long op, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, unsigned long arg5) +{ + int i = nr_multicall_ents; + multicall_list[i].op = op; + multicall_list[i].args[0] = arg1; + multicall_list[i].args[1] = arg2; + multicall_list[i].args[2] = arg3; + multicall_list[i].args[3] = arg4; + multicall_list[i].args[4] = arg5; + nr_multicall_ents = i+1; +} + static inline void execute_multicall_list(void) { if ( unlikely(nr_multicall_ents == 0) ) return; diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h b/xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h index 49d6e30b2a..0f502cfcb8 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h @@ -265,4 +265,10 @@ static inline void flush_tlb_pgtables(struct mm_struct *mm, XENO_flush_page_update_queue(); } +extern int direct_remap_area_pages(struct mm_struct *mm, + unsigned long address, + unsigned long machine_addr, + unsigned long size, + pgprot_t prot); + #endif /* _I386_PGALLOC_H */ diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h b/xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h index 0f914c7c42..0a2482f96f 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h @@ -3,8 +3,6 @@ #include -#define HAVE_ARCH_UNMAPPED_AREA - /* * The Linux memory management assumes a three-level page table setup. On * the i386, we use that, but "fold" the mid level into the top-level page @@ -114,6 +112,7 @@ extern void * high_memory; #define _PAGE_BIT_DIRTY 6 #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page, Pentium+, if present.. */ #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ +#define _PAGE_BIT_IO 9 #define _PAGE_PRESENT 0x001 #define _PAGE_RW 0x002 @@ -124,6 +123,7 @@ extern void * high_memory; #define _PAGE_DIRTY 0x040 #define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */ #define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */ +#define _PAGE_IO 0x200 #define _PAGE_PROTNONE 0x080 /* If not present */ @@ -196,6 +196,7 @@ static inline int pte_exec(pte_t pte) { return (pte).pte_low & _PAGE_USER; } static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; } static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; } static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; } +static inline int pte_io(pte_t pte) { return (pte).pte_low & _PAGE_IO; } static inline pte_t pte_rdprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; } static inline pte_t pte_exprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; } @@ -207,6 +208,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; } static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; } static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; } +static inline pte_t pte_mkio(pte_t pte) { (pte).pte_low |= _PAGE_IO; return pte; } static inline int ptep_test_and_clear_dirty(pte_t *ptep) { diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h b/xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h new file mode 100644 index 0000000000..89386f4ff8 --- /dev/null +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * proc_cmd.h + * + * Interface to /proc/cmd and /proc/xeno/privcmd. + */ + +#ifndef __PROC_CMD_H__ +#define __PROC_CMD_H__ + +#define IOCTL_PRIVCMD_HYPERCALL 0 +#define IOCTL_PRIVCMD_BLKMSG 1 +#define IOCTL_PRIVCMD_LINDEV_TO_XENDEV 2 +#define IOCTL_PRIVCMD_XENDEV_TO_LINDEV 3 + +typedef struct privcmd_hypercall +{ + unsigned long op; + unsigned long arg[5]; +} privcmd_hypercall_t; + +typedef struct privcmd_blkmsg +{ + unsigned long op; + void *buf; + int buf_size; +} privcmd_blkmsg_t; + +#endif /* __PROC_CMD_H__ */ diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/segment.h b/xenolinux-2.4.21-sparse/include/asm-xeno/segment.h index 35862eb1f2..ca13028ce0 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/segment.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/segment.h @@ -1,6 +1,9 @@ #ifndef _ASM_SEGMENT_H #define _ASM_SEGMENT_H +#ifndef __ASSEMBLY__ +#include +#endif #include #define __KERNEL_CS FLAT_RING1_CS diff --git a/xenolinux-2.4.21-sparse/mkbuildtree b/xenolinux-2.4.21-sparse/mkbuildtree index 8c02e17f1e..ffb7fde4fa 100755 --- a/xenolinux-2.4.21-sparse/mkbuildtree +++ b/xenolinux-2.4.21-sparse/mkbuildtree @@ -125,6 +125,7 @@ ln -sf ../asm-i386/math_emu.h ln -sf ../asm-i386/mc146818rtc.h ln -sf ../asm-i386/mca_dma.h ln -sf ../asm-i386/mman.h +ln -sf ../asm-i386/mmu.h ln -sf ../asm-i386/mmx.h ln -sf ../asm-i386/module.h ln -sf ../asm-i386/mpspec.h diff --git a/xenolinux-2.4.21-sparse/mm/memory.c b/xenolinux-2.4.21-sparse/mm/memory.c index 0c6d000e1f..d3833e4bf3 100644 --- a/xenolinux-2.4.21-sparse/mm/memory.c +++ b/xenolinux-2.4.21-sparse/mm/memory.c @@ -318,6 +318,13 @@ static inline int zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long ad continue; if (pte_present(pte)) { struct page *page = pte_page(pte); +#if defined(CONFIG_XENO_PRIV) + if (pte_io(pte)) { + queue_l1_entry_update( + __pa(ptep)|PGREQ_UNCHECKED_UPDATE, 0); + continue; + } +#endif if (VALID_PAGE(page) && !PageReserved(page)) freed ++; /* This will eventually call __free_pte on the pte. */ @@ -1374,6 +1381,15 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, pgd_t *pgd; pmd_t *pmd; +#if defined(CONFIG_XENO_PRIV) + /* Take care of I/O mappings right here. */ + if (vma->vm_flags & VM_IO) { + if (write_access && !(vma->vm_flags & VM_WRITE)) + return -1; + return 1; + } +#endif + current->state = TASK_RUNNING; pgd = pgd_offset(mm, address); diff --git a/xenolinux-2.4.21-sparse/mm/mprotect.c b/xenolinux-2.4.21-sparse/mm/mprotect.c new file mode 100644 index 0000000000..a6f355d03b --- /dev/null +++ b/xenolinux-2.4.21-sparse/mm/mprotect.c @@ -0,0 +1,344 @@ +/* + * linux/mm/mprotect.c + * + * (C) Copyright 1994 Linus Torvalds + */ +#include +#include +#include +#include + +#include +#include +#include + +static inline void change_pte_range(pmd_t * pmd, unsigned long address, + unsigned long size, pgprot_t newprot) +{ + pte_t * pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + if (pte_present(*pte)) { + pte_t entry; + + /* Avoid an SMP race with hardware updated dirty/clean + * bits by wiping the pte and then setting the new pte + * into place. + */ + entry = ptep_get_and_clear(pte); + set_pte(pte, pte_modify(entry, newprot)); + } + address += PAGE_SIZE; + pte++; + } while (address && (address < end)); +} + +static inline void change_pmd_range(pgd_t * pgd, unsigned long address, + unsigned long size, pgprot_t newprot) +{ + pmd_t * pmd; + unsigned long end; + + if (pgd_none(*pgd)) + return; + if (pgd_bad(*pgd)) { + pgd_ERROR(*pgd); + pgd_clear(pgd); + return; + } + pmd = pmd_offset(pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + change_pte_range(pmd, address, end - address, newprot); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address && (address < end)); +} + +static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot) +{ + pgd_t *dir; + unsigned long beg = start; + + dir = pgd_offset(current->mm, start); + flush_cache_range(current->mm, beg, end); + if (start >= end) + BUG(); + spin_lock(¤t->mm->page_table_lock); + do { + change_pmd_range(dir, start, end - start, newprot); + start = (start + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (start && (start < end)); + spin_unlock(¤t->mm->page_table_lock); + flush_tlb_range(current->mm, beg, end); + return; +} + +static inline int mprotect_fixup_all(struct vm_area_struct * vma, struct vm_area_struct ** pprev, + int newflags, pgprot_t prot) +{ + struct vm_area_struct * prev = *pprev; + struct mm_struct * mm = vma->vm_mm; + + if (prev && prev->vm_end == vma->vm_start && can_vma_merge(prev, newflags) && + !vma->vm_file && !(vma->vm_flags & VM_SHARED)) { + spin_lock(&mm->page_table_lock); + prev->vm_end = vma->vm_end; + __vma_unlink(mm, vma, prev); + spin_unlock(&mm->page_table_lock); + + kmem_cache_free(vm_area_cachep, vma); + mm->map_count--; + + return 0; + } + + spin_lock(&mm->page_table_lock); + vma->vm_flags = newflags; + vma->vm_page_prot = prot; + spin_unlock(&mm->page_table_lock); + + *pprev = vma; + + return 0; +} + +static inline int mprotect_fixup_start(struct vm_area_struct * vma, struct vm_area_struct ** pprev, + unsigned long end, + int newflags, pgprot_t prot) +{ + struct vm_area_struct * n, * prev = *pprev; + + *pprev = vma; + + if (prev && prev->vm_end == vma->vm_start && can_vma_merge(prev, newflags) && + !vma->vm_file && !(vma->vm_flags & VM_SHARED)) { + spin_lock(&vma->vm_mm->page_table_lock); + prev->vm_end = end; + vma->vm_start = end; + spin_unlock(&vma->vm_mm->page_table_lock); + + return 0; + } + n = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!n) + return -ENOMEM; + *n = *vma; + n->vm_end = end; + n->vm_flags = newflags; + n->vm_raend = 0; + n->vm_page_prot = prot; + if (n->vm_file) + get_file(n->vm_file); + if (n->vm_ops && n->vm_ops->open) + n->vm_ops->open(n); + vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT; + lock_vma_mappings(vma); + spin_lock(&vma->vm_mm->page_table_lock); + vma->vm_start = end; + __insert_vm_struct(current->mm, n); + spin_unlock(&vma->vm_mm->page_table_lock); + unlock_vma_mappings(vma); + + return 0; +} + +static inline int mprotect_fixup_end(struct vm_area_struct * vma, struct vm_area_struct ** pprev, + unsigned long start, + int newflags, pgprot_t prot) +{ + struct vm_area_struct * n; + + n = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); + if (!n) + return -ENOMEM; + *n = *vma; + n->vm_start = start; + n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT; + n->vm_flags = newflags; + n->vm_raend = 0; + n->vm_page_prot = prot; + if (n->vm_file) + get_file(n->vm_file); + if (n->vm_ops && n->vm_ops->open) + n->vm_ops->open(n); + lock_vma_mappings(vma); + spin_lock(&vma->vm_mm->page_table_lock); + vma->vm_end = start; + __insert_vm_struct(current->mm, n); + spin_unlock(&vma->vm_mm->page_table_lock); + unlock_vma_mappings(vma); + + *pprev = n; + + return 0; +} + +static inline int mprotect_fixup_middle(struct vm_area_struct * vma, struct vm_area_struct ** pprev, + unsigned long start, unsigned long end, + int newflags, pgprot_t prot) +{ + struct vm_area_struct * left, * right; + + left = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!left) + return -ENOMEM; + right = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!right) { + kmem_cache_free(vm_area_cachep, left); + return -ENOMEM; + } + *left = *vma; + *right = *vma; + left->vm_end = start; + right->vm_start = end; + right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT; + left->vm_raend = 0; + right->vm_raend = 0; + if (vma->vm_file) + atomic_add(2,&vma->vm_file->f_count); + if (vma->vm_ops && vma->vm_ops->open) { + vma->vm_ops->open(left); + vma->vm_ops->open(right); + } + vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT; + vma->vm_raend = 0; + vma->vm_page_prot = prot; + lock_vma_mappings(vma); + spin_lock(&vma->vm_mm->page_table_lock); + vma->vm_start = start; + vma->vm_end = end; + vma->vm_flags = newflags; + __insert_vm_struct(current->mm, left); + __insert_vm_struct(current->mm, right); + spin_unlock(&vma->vm_mm->page_table_lock); + unlock_vma_mappings(vma); + + *pprev = right; + + return 0; +} + +static int mprotect_fixup(struct vm_area_struct * vma, struct vm_area_struct ** pprev, + unsigned long start, unsigned long end, unsigned int newflags) +{ + pgprot_t newprot; + int error; + + if (newflags == vma->vm_flags) { + *pprev = vma; + return 0; + } + newprot = protection_map[newflags & 0xf]; + if (start == vma->vm_start) { + if (end == vma->vm_end) + error = mprotect_fixup_all(vma, pprev, newflags, newprot); + else + error = mprotect_fixup_start(vma, pprev, end, newflags, newprot); + } else if (end == vma->vm_end) + error = mprotect_fixup_end(vma, pprev, start, newflags, newprot); + else + error = mprotect_fixup_middle(vma, pprev, start, end, newflags, newprot); + + if (error) + return error; + + change_protection(start, end, newprot); + return 0; +} + +asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) +{ + unsigned long nstart, end, tmp; + struct vm_area_struct * vma, * next, * prev; + int error = -EINVAL; + + if (start & ~PAGE_MASK) + return -EINVAL; + len = PAGE_ALIGN(len); + end = start + len; + if (end < start) + return -EINVAL; + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return -EINVAL; + if (end == start) + return 0; + + down_write(¤t->mm->mmap_sem); + + vma = find_vma_prev(current->mm, start, &prev); + error = -ENOMEM; + if (!vma || vma->vm_start > start) + goto out; + +#if defined(CONFIG_XENO_PRIV) + /* mprotect() unsupported for I/O mappings in Xenolinux. */ + error = -EINVAL; + if (vma->vm_flags & VM_IO) + goto out; +#endif + + for (nstart = start ; ; ) { + unsigned int newflags; + int last = 0; + + /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ + + newflags = prot | (vma->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC)); + if ((newflags & ~(newflags >> 4)) & 0xf) { + error = -EACCES; + goto out; + } + + if (vma->vm_end > end) { + error = mprotect_fixup(vma, &prev, nstart, end, newflags); + goto out; + } + if (vma->vm_end == end) + last = 1; + + tmp = vma->vm_end; + next = vma->vm_next; + error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); + if (error) + goto out; + if (last) + break; + nstart = tmp; + vma = next; + if (!vma || vma->vm_start != nstart) { + error = -ENOMEM; + goto out; + } + } + if (next && prev->vm_end == next->vm_start && can_vma_merge(next, prev->vm_flags) && + !prev->vm_file && !(prev->vm_flags & VM_SHARED)) { + spin_lock(&prev->vm_mm->page_table_lock); + prev->vm_end = next->vm_end; + __vma_unlink(prev->vm_mm, next, prev); + spin_unlock(&prev->vm_mm->page_table_lock); + + kmem_cache_free(vm_area_cachep, next); + prev->vm_mm->map_count--; + } +out: + up_write(¤t->mm->mmap_sem); + return error; +} diff --git a/xenolinux-2.4.21-sparse/mm/mremap.c b/xenolinux-2.4.21-sparse/mm/mremap.c index a2e0d860dd..a452b467f7 100644 --- a/xenolinux-2.4.21-sparse/mm/mremap.c +++ b/xenolinux-2.4.21-sparse/mm/mremap.c @@ -293,6 +293,13 @@ unsigned long do_mremap(unsigned long addr, !vm_enough_memory((new_len - old_len) >> PAGE_SHIFT)) goto out; +#if defined(CONFIG_XENO_PRIV) + /* mremap() unsupported for I/O mappings in Xenolinux. */ + ret = -EINVAL; + if (vma->vm_flags & VM_IO) + goto out; +#endif + /* old_len exactly to the end of the area.. * And we're not relocating the area. */ diff --git a/xenolinux-2.4.21-sparse/mm/vmalloc.c b/xenolinux-2.4.21-sparse/mm/vmalloc.c new file mode 100644 index 0000000000..015cad0780 --- /dev/null +++ b/xenolinux-2.4.21-sparse/mm/vmalloc.c @@ -0,0 +1,334 @@ +/* + * linux/mm/vmalloc.c + * + * Copyright (C) 1993 Linus Torvalds + * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 + * SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian , May 2000 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +rwlock_t vmlist_lock = RW_LOCK_UNLOCKED; +struct vm_struct * vmlist; + +static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size) +{ + pte_t * pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t page; + page = ptep_get_and_clear(pte); + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + if (pte_present(page)) { + struct page *ptpage = pte_page(page); + if (VALID_PAGE(ptpage) && (!PageReserved(ptpage))) + __free_page(ptpage); + continue; + } + printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n"); + } while (address < end); +} + +static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size) +{ + pmd_t * pmd; + unsigned long end; + + if (pgd_none(*dir)) + return; + if (pgd_bad(*dir)) { + pgd_ERROR(*dir); + pgd_clear(dir); + return; + } + pmd = pmd_offset(dir, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + free_area_pte(pmd, address, end - address); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +void vmfree_area_pages(unsigned long address, unsigned long size) +{ + pgd_t * dir; + unsigned long end = address + size; + + dir = pgd_offset_k(address); + flush_cache_all(); + do { + free_area_pmd(dir, address, end - address); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + flush_tlb_all(); +} + +static inline int alloc_area_pte (pte_t * pte, unsigned long address, + unsigned long size, int gfp_mask, pgprot_t prot) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + struct page * page; + spin_unlock(&init_mm.page_table_lock); + page = alloc_page(gfp_mask); + spin_lock(&init_mm.page_table_lock); + if (!pte_none(*pte)) + printk(KERN_ERR "alloc_area_pte: page already exists\n"); + if (!page) + return -ENOMEM; + set_pte(pte, mk_pte(page, prot)); + address += PAGE_SIZE; + pte++; + } while (address < end); + return 0; +} + +static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask, pgprot_t prot) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + pte_t * pte = pte_alloc(&init_mm, pmd, address); + if (!pte) + return -ENOMEM; + if (alloc_area_pte(pte, address, end - address, gfp_mask, prot)) + return -ENOMEM; + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + return 0; +} + +inline int vmalloc_area_pages (unsigned long address, unsigned long size, + int gfp_mask, pgprot_t prot) +{ + pgd_t * dir; + unsigned long end = address + size; + int ret; + + dir = pgd_offset_k(address); + spin_lock(&init_mm.page_table_lock); + do { + pmd_t *pmd; + + pmd = pmd_alloc(&init_mm, dir, address); + ret = -ENOMEM; + if (!pmd) + break; + + ret = -ENOMEM; + if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot)) + break; + + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + + ret = 0; + } while (address && (address < end)); + spin_unlock(&init_mm.page_table_lock); + flush_cache_all(); + return ret; +} + +struct vm_struct * get_vm_area(unsigned long size, unsigned long flags) +{ + unsigned long addr, next; + struct vm_struct **p, *tmp, *area; + + area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; + + size += PAGE_SIZE; + if (!size) { + kfree (area); + return NULL; + } + + addr = VMALLOC_START; + write_lock(&vmlist_lock); + for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { + if ((size + addr) < addr) + goto out; + if (size + addr <= (unsigned long) tmp->addr) + break; + next = tmp->size + (unsigned long) tmp->addr; + if (next > addr) + addr = next; + if (addr > VMALLOC_END-size) + goto out; + } + area->flags = flags; + area->addr = (void *)addr; + area->size = size; + area->next = *p; + *p = area; + write_unlock(&vmlist_lock); + return area; + +out: + write_unlock(&vmlist_lock); + kfree(area); + return NULL; +} + +void vfree(void * addr) +{ + struct vm_struct **p, *tmp; + + if (!addr) + return; + if ((PAGE_SIZE-1) & (unsigned long) addr) { + printk(KERN_ERR "Trying to vfree() bad address (%p)\n", addr); + return; + } + write_lock(&vmlist_lock); + for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == addr) { + *p = tmp->next; +#ifdef CONFIG_XENO_PRIV + if (tmp->flags & VM_IOREMAP) + zap_page_range(&init_mm, VMALLOC_VMADDR(tmp->addr), tmp->size); + else +#endif + vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size); + write_unlock(&vmlist_lock); + kfree(tmp); + return; + } + } + write_unlock(&vmlist_lock); + printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr); +} + +void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot) +{ + void * addr; + struct vm_struct *area; + + size = PAGE_ALIGN(size); + if (!size || (size >> PAGE_SHIFT) > num_physpages) + return NULL; + area = get_vm_area(size, VM_ALLOC); + if (!area) + return NULL; + addr = area->addr; + if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask, prot)) { + vfree(addr); + return NULL; + } + return addr; +} + +long vread(char *buf, char *addr, unsigned long count) +{ + struct vm_struct *tmp; + char *vaddr, *buf_start = buf; + unsigned long n; + + /* Don't allow overflow */ + if ((unsigned long) addr + count < count) + count = -(unsigned long) addr; + + read_lock(&vmlist_lock); + for (tmp = vmlist; tmp; tmp = tmp->next) { + vaddr = (char *) tmp->addr; + if (addr >= vaddr + tmp->size - PAGE_SIZE) + continue; + while (addr < vaddr) { + if (count == 0) + goto finished; + *buf = '\0'; + buf++; + addr++; + count--; + } + n = vaddr + tmp->size - PAGE_SIZE - addr; + do { + if (count == 0) + goto finished; + *buf = *addr; + buf++; + addr++; + count--; + } while (--n > 0); + } +finished: + read_unlock(&vmlist_lock); + return buf - buf_start; +} + +long vwrite(char *buf, char *addr, unsigned long count) +{ + struct vm_struct *tmp; + char *vaddr, *buf_start = buf; + unsigned long n; + + /* Don't allow overflow */ + if ((unsigned long) addr + count < count) + count = -(unsigned long) addr; + + read_lock(&vmlist_lock); + for (tmp = vmlist; tmp; tmp = tmp->next) { + vaddr = (char *) tmp->addr; + if (addr >= vaddr + tmp->size - PAGE_SIZE) + continue; + while (addr < vaddr) { + if (count == 0) + goto finished; + buf++; + addr++; + count--; + } + n = vaddr + tmp->size - PAGE_SIZE - addr; + do { + if (count == 0) + goto finished; + *addr = *buf; + buf++; + addr++; + count--; + } while (--n > 0); + } +finished: + read_unlock(&vmlist_lock); + return buf - buf_start; +} -- 2.30.2